middleware.CORSConfig can not be configured per path
rpstw opened this issue · comments
Issue Description
The following code tris to configure CORS per path.However, due to optionsMethodHandler
ignoring all configured middlewares, a preflight request will receive a bad response which contains no Access-Control-Allow headers.
e.Add(
http.MethodGet,
"/some/path",
SomeHandlerFunc,
middleware.CORSWithConfig(middleware.CORSConfig{
AllowCredentials: true,
}),
)
Checklist
- Dependencies installed
- No typos
- Searched existing issues and docs
Expected behaviour
curl -vL -X OPTIONS '10.20.0.23:3323/some-path?' -H Origin:https://some-origin.com
> OPTIONS /some-path HTTP/1.1
> Host: 10.20.0.23:3323
> User-Agent: curl/7.68.0
> Accept: */*
> Origin:https://some-origin.com
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 204 No Content
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Some-Headers
< Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
< Access-Control-Allow-Origin: https://some-origin.com
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Date: Mon, 08 Apr 2024 06:29:02 GMT
<
* Connection #0 to host 10.20.0.23 left intact
Actual behaviour
curl -vL -X OPTIONS '10.20.0.23:3323/some-path' -H Origin:https://some-origin.com
* Trying 10.20.0.23:3323...
* TCP_NODELAY set
* Connected to 10.20.0.23 (10.20.0.23) port 3323 (#0)
> OPTIONS /some-path HTTP/1.1
> Host: 10.20.0.23:3323
> User-Agent: curl/7.68.0
> Accept: */*
> Origin:https://some-origin.com
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 204 No Content
< Allow: OPTIONS, GET
< Date: Mon, 08 Apr 2024 06:37:17 GMT
<
* Connection #0 to host 10.20.0.23 left intact
Steps to reproduce
As described above
Working code to debug
As described above
Version/commit
tried 4.11.4 and 4.10.2
Workarounds tried
As #2039 inspired, configuring a custom OPTIONS
route can bypass the code where optionsMethodHandler
ignoring middlewares
e.Add(
http.MethodOptions,
"/some-path",
func(c echo.Context) error {
c.Response().Header().Add(echo.HeaderAllow, "GET,OPTIONS")
return c.NoContent(http.StatusNoContent)
},
middleware.CORSWithConfig(middleware.CORSConfig{
AllowCredentials: true,
}),
)
I'm not sure if I'm configuring CORS in a popular doable way, also the reproducible example is excerpted from a development environment which may not be as realistic as a real prod server case. Any suggestions are welcome.
@rpstw Note that curl -vL -X OPTIONS '10.20.0.23:3323/some-path?' -H Origin:https://some-origin.com
does not correspond to a CORS-preflight request: it's missing an Access-Control-Request-Method
header. Therefore, I wouldn't expect a properly implemented CORS middleware to include CORS headers in a response to such a request.
As for applying different CORS middleware on different routes, I believe that Echo allows you to do that. This example uses a different CORS library, but you should be able to adapt it to your needs.
When you add GET route with CORS middleware with
e.Add(
http.MethodGet,
"/some/path",
SomeHandlerFunc,
middleware.CORSWithConfig(middleware.CORSConfig{
AllowCredentials: true,
}),
)
Echo router registers only node matching GET method in its internal routing tree. So when you issue OPTION method call to same path the CORS middleware do not get executed as it is tied (wrapping it) to GET handler. So CORS middleware is best to be used with e.Use()
by it to all routes or registering .OPTIONS("path"...
to be able to match only some of the requests
p.s. if choose to register own OPTIONS routes you can use echo.MethodNotAllowedHandler
handler function
Line 356 in 88c379f