func wouldMatch(router *mux.Router, rq *http.Request, method string) bool { savedMethod := rq.Method rq.Method = method defer func() { rq.Method = savedMethod }() var matchInfo mux.RouteMatch return router.Match(rq, &matchInfo) }
// Returns a top-level HTTP handler for a Router. This adds behavior for URLs that don't // match anything -- it handles the OPTIONS method as well as returning either a 404 or 405 // for URLs that don't match a route. func wrapRouter(sc *ServerContext, privs handlerPrivs, router *mux.Router) http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, rq *http.Request) { fixQuotedSlashes(rq) var match mux.RouteMatch if router.Match(rq, &match) { router.ServeHTTP(response, rq) } else { // Log the request h := newHandler(sc, privs, response, rq) h.logRequestLine() // What methods would have matched? var options []string for _, method := range []string{"GET", "HEAD", "POST", "PUT", "DELETE"} { if wouldMatch(router, rq, method) { options = append(options, method) } } if len(options) == 0 { h.writeStatus(http.StatusNotFound, "unknown URL") } else { response.Header().Add("Allow", strings.Join(options, ", ")) if rq.Method != "OPTIONS" { h.writeStatus(http.StatusMethodNotAllowed, "") } } } }) }
// TestErrorExpectedResponse is the generic test code for testing for a bad response func TestErrorExpectedResponse(t *testing.T, router *mux.Router, method, url, route string, data io.Reader, accessToken, msg string, code int, assertExpectations func()) { // Prepare a request r, err := http.NewRequest( method, url, data, ) assert.NoError(t, err) // Optionally add a bearer token to headers if accessToken != "" { r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken)) } // Check the routing match := new(mux.RouteMatch) router.Match(r, match) if assert.NotNil(t, match.Route) { assert.Equal(t, route, match.Route.GetName()) } // And serve the request w := httptest.NewRecorder() router.ServeHTTP(w, r) TestResponseForError(t, w, msg, code) assertExpectations() }
// Returns a top-level HTTP handler for a Router. This adds behavior for URLs that don't // match anything -- it handles the OPTIONS method as well as returning either a 404 or 405 // for URLs that don't match a route. func wrapRouter(sc *ServerContext, privs handlerPrivs, router *mux.Router) http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, rq *http.Request) { fixQuotedSlashes(rq) var match mux.RouteMatch // Inject CORS if enabled and requested and not admin port originHeader := rq.Header["Origin"] if privs != adminPrivs && sc.config.CORS != nil && len(originHeader) > 0 { origin := matchedOrigin(sc.config.CORS.Origin, originHeader) response.Header().Add("Access-Control-Allow-Origin", origin) response.Header().Add("Access-Control-Allow-Credentials", "true") response.Header().Add("Access-Control-Allow-Headers", strings.Join(sc.config.CORS.Headers, ", ")) } if router.Match(rq, &match) { router.ServeHTTP(response, rq) } else { // Log the request h := newHandler(sc, privs, response, rq, false) h.logRequestLine() // What methods would have matched? var options []string for _, method := range []string{"GET", "HEAD", "POST", "PUT", "DELETE"} { if wouldMatch(router, rq, method) { options = append(options, method) } } if len(options) == 0 { h.writeStatus(http.StatusNotFound, "unknown URL") } else { response.Header().Add("Allow", strings.Join(options, ", ")) if privs != adminPrivs && sc.config.CORS != nil && len(originHeader) > 0 { response.Header().Add("Access-Control-Max-Age", strconv.Itoa(sc.config.CORS.MaxAge)) response.Header().Add("Access-Control-Allow-Methods", strings.Join(options, ", ")) } if rq.Method != "OPTIONS" { h.writeStatus(http.StatusMethodNotAllowed, "") } else { h.writeStatus(http.StatusNoContent, "") } } h.logDuration(true) } }) }
// Returns a top-level HTTP handler for a Router. This adds behavior for URLs that don't // match anything -- it handles the OPTIONS method as well as returning either a 404 or 405 // for URLs that don't match a route. func wrapRouter(sc *ServerContext, privs handlerPrivs, router *mux.Router) http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, rq *http.Request) { fixQuotedSlashes(rq) var match mux.RouteMatch //if sc.config.CORS != nil { response.Header().Add("Access-Control-Allow-Origin", "*") response.Header().Add("Access-Control-Allow-Credentials", "true") response.Header().Add("Access-Control-Allow-Headers", "DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type") // } if router.Match(rq, &match) { router.ServeHTTP(response, rq) } else { // Log the request h := newHandler(sc, privs, response, rq) h.logRequestLine() // What methods would have matched? var options []string for _, method := range []string{"GET", "HEAD", "POST", "PUT", "DELETE"} { if wouldMatch(router, rq, method) { options = append(options, method) } } if len(options) == 0 { h.writeStatus(http.StatusNotFound, "unknown URL") } else { response.Header().Add("Allow", strings.Join(options, ", ")) //if sc.config.CORS != nil { response.Header().Add("Access-Control-Max-Age", "1728000") response.Header().Add("Access-Control-Allow-Methods", strings.Join(options, ", ")) // } if rq.Method != "OPTIONS" { h.writeStatus(http.StatusMethodNotAllowed, "") } } } }) }