Skip to content

CORS: OPTIONS call not handled #381

@pierreprinetti

Description

@pierreprinetti

What version of Go are you running?
go version go1.10.2 darwin/amd64

What version of gorilla/mux are you at?
c856192

Describe your problem

  • Create a router
  • Register a route with .Methods("GET")
  • Make the router use the new CORSMiddleware
  • Call OPTIONS on the route
  • Expect a 200 OK with the Access-Control-Allowed-Methods set to GET,OPTIONS; get instead a 405.

The code that is supposed to handle OPTIONS requests (below) is never reached, unless OPTIONS is a registered method for the route.

mux/middleware.go

Lines 64 to 66 in c856192

if req.Method == "OPTIONS" {
return
}

Paste a minimal, runnable, reproduction of your issue below

Add this test to middleware_test.go

func TestCORSMiddlewareOPTIONS(t *testing.T) {
	router := NewRouter()

	cases := []struct {
		path                   string
		response               string
		method                 string
		testURL                string
		expectedAllowedMethods string
	}{
		{"/g/{o}", "a", "POST", "/g/asdf", "POST,PUT,GET,OPTIONS"},
		{"/g/{o}", "b", "PUT", "/g/bla", "POST,PUT,GET,OPTIONS"},
		{"/g/{o}", "c", "GET", "/g/orilla", "POST,PUT,GET,OPTIONS"},
		{"/g", "d", "POST", "/g", "POST,OPTIONS"},
	}

	for _, tt := range cases {
		router.HandleFunc(tt.path, stringHandler(tt.response)).Methods(tt.method)
	}

	router.Use(CORSMethodMiddleware(router))

	for _, tt := range cases {
		rr := httptest.NewRecorder()
		req := newRequest("OPTIONS", tt.testURL)

		router.ServeHTTP(rr, req)

		allowedMethods := rr.HeaderMap.Get("Access-Control-Allow-Methods")

		if want, have := 200, rr.Result().StatusCode; have != want {
			t.Errorf("Expected status code %d, found %d", want, have)
		}

		if allowedMethods != tt.expectedAllowedMethods {
			t.Errorf("Expected Access-Control-Allow-Methods '%s', found '%s'", tt.expectedAllowedMethods, allowedMethods)
		}
	}
}

Note that this new test passes if OPTIONS is explicitly set as a method in the test-table:

		{"/g/{o}", "a", "POST", "/g/asdf", "POST,PUT,GET,OPTIONS"},
		{"/g/{o}", "b", "PUT", "/g/bla", "POST,PUT,GET,OPTIONS"},
		{"/g/{o}", "c", "GET", "/g/orilla", "POST,PUT,GET,OPTIONS"},
		{"/g", "d", "POST", "/g", "POST,OPTIONS"},
		{"/g", "", "OPTIONS", "/g", "POST,OPTIONS"},
		{"/g/{o}", "", "OPTIONS", "/g/orilla", "POST,PUT,GET,OPTIONS"},

I suspect this line to be the problem:

mux/mux.go

Line 88 in c856192

if match.MatchErr == nil {

In Router#Match, the middlewares are only triggered if the method matches a route.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions