0

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

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

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

所以我在我的请求/响应堆栈中使用middleware.CORSWithConfigw/a 。middleware.ProxyWithConfig

我看到一些奇怪的Access-Control-Allow-Origins标题,其中从代理服务到我的 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]"),
            })
    )
}
4

1 回答 1

2

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

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]"),
        })
)

EchoRequest::Before()钩子的文档:https ://echo.labstack.com/guide/response#before-response

于 2019-10-10T21:14:52.100 回答