1package middleware 2 3import ( 4 "context" 5 "net/http" 6 "strings" 7 8 "github.com/go-chi/chi" 9) 10 11var ( 12 // URLFormatCtxKey is the context.Context key to store the URL format data 13 // for a request. 14 URLFormatCtxKey = &contextKey{"URLFormat"} 15) 16 17// URLFormat is a middleware that parses the url extension from a request path and stores it 18// on the context as a string under the key `middleware.URLFormatCtxKey`. The middleware will 19// trim the suffix from the routing path and continue routing. 20// 21// Routers should not include a url parameter for the suffix when using this middleware. 22// 23// Sample usage.. for url paths: `/articles/1`, `/articles/1.json` and `/articles/1.xml` 24// 25// func routes() http.Handler { 26// r := chi.NewRouter() 27// r.Use(middleware.URLFormat) 28// 29// r.Get("/articles/{id}", ListArticles) 30// 31// return r 32// } 33// 34// func ListArticles(w http.ResponseWriter, r *http.Request) { 35// urlFormat, _ := r.Context().Value(middleware.URLFormatCtxKey).(string) 36// 37// switch urlFormat { 38// case "json": 39// render.JSON(w, r, articles) 40// case "xml:" 41// render.XML(w, r, articles) 42// default: 43// render.JSON(w, r, articles) 44// } 45// } 46// 47func URLFormat(next http.Handler) http.Handler { 48 fn := func(w http.ResponseWriter, r *http.Request) { 49 ctx := r.Context() 50 51 var format string 52 path := r.URL.Path 53 54 if strings.Index(path, ".") > 0 { 55 base := strings.LastIndex(path, "/") 56 idx := strings.Index(path[base:], ".") 57 58 if idx > 0 { 59 idx += base 60 format = path[idx+1:] 61 62 rctx := chi.RouteContext(r.Context()) 63 rctx.RoutePath = path[:idx] 64 } 65 } 66 67 r = r.WithContext(context.WithValue(ctx, URLFormatCtxKey, format)) 68 69 next.ServeHTTP(w, r) 70 } 71 return http.HandlerFunc(fn) 72} 73