Echo CORS with/ Proxy middlewares causes problems with/ Access-Allow-Origins response header

Echo CORS w/ Proxy middlewares causes problems w/ Access-Allow-Origins response header

我正在使用 LabStack 的 Golang Echo 框架构建服务。

其中一个路由需要代理后端服务的请求和响应。

但我也需要 CORS 来处理此服务。

所以我在 request/response 堆栈中使用 middleware.CORSWithConfigmiddleware.ProxyWithConfig

我发现 Access-Control-Allow-Origins header 有一些奇怪之处,其中 header 的值在代理服务对我的 Echo 服务器 * 的响应中,但是一旦它通过代理,它就会在返回到客户端时变为 *, *。 我开始看到以下与 CORS 违规相关的浏览器错误:

VM1627:362 Access to XMLHttpRequest at 'http://localhost:6273/' from origin 'http://localhost:8002' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

有人遇到过这个吗?任何人都知道为什么会发生这种情况,也许有解决办法?

下面是一些示例代码:

package main

func singleTargetBalancer(url *url.URL) middleware.ProxyBalancer {
    targetURL := []*middleware.ProxyTarget{
        {
            URL: url,
        },
    }
    return middleware.NewRoundRobinBalancer(targetURL)
}

func Noop(ctx echo.Context) (err error) {
    ctx.String(
        http.StatusNotImplemented,
        "No op handler should never be reached!",
    )

    return err
}

func main() {
        e := echo.New()
    e.HideBanner = true
    e.Use(
        middleware.CORSWithConfig(middlewares.CustomCorsConfig),
        middlewares.ThriftMetrics(),
    )

        // Have to use a Noop handler since we're not trying to set up a full-on proxy for the backend service.  We only want this one route to be proxied.
        e.POST(
        "/",
        handlers.Noop,
        middleware.ProxyWithConfig(middleware.ProxyConfig{
             Balancer: singleTargetBalancer("[backend service URL]"),
            })
    )
}

我最终通过编写自定义 Echo 中间件来解决这个问题,以便在 Echo 的代理中间件可以将 headers 发送回客户端之前挂接到响应。

func setResponseACAOHeaderFromRequest (req http.Request, resp echo.Response) {
    resp.Header().Set(echo.HeaderAccessControlAllowOrigin, 
    req.Header.Get(echo.HeaderOrigin))
}

func ACAOHeaderOverwriteMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(ctx echo.Context) error {
        ctx.Response().Before(func() {
            setResponseACAOHeaderFromRequest(*ctx.Request(), *ctx.Response())
        })
        return next(ctx)
    }
}

然后把这个中间件放在e.Use()右边你的代理中间件之前:

e.POST(
        "/",
        handlers.Noop,
        ACAOHeaderOverwriteMiddleware,
        middleware.ProxyWithConfig(middleware.ProxyConfig{
             Balancer: singleTargetBalancer("[backend service URL]"),
        })
)

Echo Request::Before() 挂钩的文档:https://echo.labstack.com/guide/response#before-response