Echo: CORS middleware on router group

Created on 4 Oct 2015  ยท  22Comments  ยท  Source: labstack/echo

CORS middleware does not seem to work when used on router group. It only works when used on the main router. I do not want to expose all APIs on my server for CORS.

bug

Most helpful comment

I'm having this problem too when sending Authorization header with "POST", the request method automatically changes to OPTIONS. I have added echo.OPTIONS inside AllowMethods parameters but it still gives me 405 response code, Method Not Allowed.
e := echo.New() r := e.Group("/restricted") r.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{"http://localhost:8080"}, AllowMethods: []string{ echo.GET, echo.PUT, echo.POST, echo.DELETE, echo.OPTIONS}, AllowHeaders: []string{ echo.HeaderAuthorization, echo.HeaderContentType}, }))

But when I remove the router Group, the CORS works.

All 22 comments

Can you provide some code explaining actual and expected behavior?

I am trying to setup a server where only a few APIs ( the ones used for auth) are enabled for CORS. The APIs are being consumed from angular client.

If i setup the server like:

router := echo.New()
router.Use(mw.Logger())
corsMw := cors.New(cors.Options{
            AllowedOrigins:   allowedOrigins,
            AllowedHeaders:   []string{"*"},
            ExposedHeaders:   []string{"X-token"},
            AllowCredentials: true,
}).Handler

    //used on the main router
router.Use(corsMw) 
rga := router.Group("/auth")
rgo := router.Group("/others")

It works fine. However then the CORS mw will be used for both /auth and /others.

If i try to setup the server like

router := echo.New()
router.Use(mw.Logger())
rga := router.Group("/auth")
rgo := router.Group("/others")
corsMw := cors.New(cors.Options{
            AllowedOrigins:   allowedOrigins,
            AllowedHeaders:   []string{"*"},
            ExposedHeaders:   []string{"X-token"},
            AllowCredentials: true,
}).Handler
    //used on a group
rga.Use(corsMw) 

It does not work. The call never reaches CORS middleware. A 404 is returned (I think it said OPTIONS /auth/authenticate is not a valid path)

Tried the following code and looks like it works as expected:

package main

import (
    "github.com/labstack/echo"
    mw "github.com/labstack/echo/middleware"
    "github.com/rs/cors"
)

func main() {
    router := echo.New()
    router.Use(mw.Logger())

    rga := router.Group("/auth")
    rgo := router.Group("/others")

    corsMw := cors.New(cors.Options{
        AllowedOrigins: []string{"*"},
    }).Handler
    rga.Use(corsMw)

    rga.Get("", func(c *echo.Context) error {
        return c.String(200, "/auth")
    })

    rgo.Get("", func(c *echo.Context) error {
        return c.String(200, "/others")
    })

    router.Run(":1323")
}

/auth

โฏ curl -D - -H 'Origin: http://foo.com' http://localhost:1323/auth
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.com
Content-Type: text/plain
Vary: Origin
Date: Mon, 05 Oct 2015 16:29:18 GMT
Content-Length: 5

/auth%

/others

โฏ curl -D - -H 'Origin: http://foo.com' http://localhost:1323/others
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Mon, 05 Oct 2015 16:30:41 GMT
Content-Length: 7

/others%

Did some more testing. Turns out that the difference is in how it processes an OPTIONS request. Use the same program as above and execute

curl -X OPTIONS http://localhost:1323/auth

It says Not found

Change the above program from

    rga.Use(corsMw)

to

    router.Use(corsMw)

The same curl command will work.

@mandeepbrar As it goes through a critical path, this issue is being fixed in a different branch - https://github.com/labstack/echo/tree/issue-228, once stabilizes I will merge it back to the master. This fix will also addresses #204 and #223. All tests are passing. Can you trying to pull from this branch and test?

The same case is still not working.

Just the error got changed. Instead of "Not found", its saying 405 "Method Not allowed" in case of rga.Use(corsMw).

Same thing works when using router.Use(corsMw)

Can you try now?

The behavior just reversed. Not working for router.Use(corsMw) -- (Method not allowed). Working for rga.Use(corsMw)

I am using the following code to test, can you double check? (I have a new commit, which should not have impacted this logic, its just a temporary removal of 405 handling)

package main

import (
    "github.com/labstack/echo"
    mw "github.com/labstack/echo/middleware"
    "github.com/rs/cors"
)

func main() {
    router := echo.New()
    router.Use(mw.Logger())

    rga := router.Group("/auth")
    rgo := router.Group("/others")

    rga.Use(cors.Default().Handler)
    // router.Use(cors.Default().Handler)

    rga.Get("", func(c *echo.Context) error {
        return c.String(200, "/auth")
    })

    rgo.Get("", func(c *echo.Context) error {
        return c.String(200, "/others")
    })

    router.Run(":1323")
}

This is merged into master, do we sitl have this issue?

Closing as there is no response from the OP.

Sorry for the delay. This is still not working. In the program that you had used. Just changed

//rga.Use(cors.Default().Handler)
router.Use(cors.Default().Handler)

This doesnt work for me with the latest build from github. Used

curl -X OPTIONS http://localhost:1323/auth

IC, if you move up router.Use(cors.Default().Handler) next to logger middleware it should work.

Yes it does. My mistake and Thank you. This is fixed.

sorry, a cors option problem. It's down.

Is this fixed? I got same problem with echo 3.0.3

@Arch-Mage Can you check if this works in master?

I'm having this problem too when sending Authorization header with "POST", the request method automatically changes to OPTIONS. I have added echo.OPTIONS inside AllowMethods parameters but it still gives me 405 response code, Method Not Allowed.
e := echo.New() r := e.Group("/restricted") r.Use(middleware.CORSWithConfig(middleware.CORSConfig{ AllowOrigins: []string{"http://localhost:8080"}, AllowMethods: []string{ echo.GET, echo.PUT, echo.POST, echo.DELETE, echo.OPTIONS}, AllowHeaders: []string{ echo.HeaderAuthorization, echo.HeaderContentType}, }))

But when I remove the router Group, the CORS works.

IC, if you move up router.Use(cors.Default().Handler) next to logger middleware it should work.

Hello, am still experiencing this issue on echo 3.3, have tried this workaround but getting this compile error:
cannot use cors.Default().Handler (type func(http.Handler) http.Handler) as type echo.MiddlewareFunc in argument to router.Use

Anyone can resolve it?

I just create an options middleware that usually accepts all options requests:

func AllowOptionsRequests() echo.MiddlewareFunc {
    return func(next echo.HandlerFunc) echo.HandlerFunc {
        return func(c echo.Context) error {
            if c.Request().Method == echo.OPTIONS {

                allowHeaders := []string{
                    echo.HeaderContentType,
                    // ... other headers you may need to allow
                }
                c.Response().Header().Set(echo.HeaderAccessControlAllowOrigin, "*")
                c.Response().Header().Set(echo.HeaderAccessControlAllowHeaders, strings.Join(allowHeaders, ","))

                return c.JSON(http.StatusOK, "ok")
            }
            return next(c)
        }
    }
}

Unfortunately this is still an issue with the latest echo v4.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rocketspacer picture rocketspacer  ยท  27Comments

yenskillah picture yenskillah  ยท  24Comments

andreiavrammsd picture andreiavrammsd  ยท  32Comments

asdine picture asdine  ยท  14Comments

mrLSD picture mrLSD  ยท  11Comments