代码之家  ›  专栏  ›  技术社区  ›  RavenHursT

带有代理中间件的Echo-CORS在带有Access-Allow-Origins响应头的情况下导致问题

  •  0
  • RavenHursT  · 技术社区  · 5 年前

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

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

    所以我用 middleware.CORSWithConfig 沿w/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]"),
                })
        )
    }
    
    0 回复  |  直到 5 年前
        1
  •  3
  •   RavenHursT    5 年前

    我最终解决了这个问题,在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]"),
            })
    )
    

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