coupergateway / couper

Couper is a lightweight API gateway designed to support developers in building and operating API-driven Web projects
https://couper.io
MIT License
85 stars 15 forks source link

duplicate CORS headers leads to browser CORS errors #777

Closed malud closed 7 months ago

malud commented 1 year ago

Describe the bug If you connect a backend api via proxy block and you have CORS options enabled and the api sends also such headers this leads to duplicate cors headers which the browser does not allow.

Current workaround is to add remove_response_headers = ["access-control-allow-origin", "access-control-allow-credentials"] to your backend definition.

johakoch commented 9 months ago

The problem may also occur with request:

    endpoint "/foo" {
      request "r" {
        url = "/bar"
        backend = "be"
      }
      response {
        headers = backend_responses.r.headers
      }
    }
johakoch commented 8 months ago

The CORS response headers must not be set/added before

    nextHandler.ServeHTTP(rw, req)

in CORS.ServeNextHTTP(). Instead we could register headers to remove/set/add with the writer.Response and execute the modifications after (? or before?) r.applyModifier().

filex commented 8 months ago

The desired effect is that the a-c-a-* headers generated by Couper's cors block always win.(we do not want to be "smart" and try to merge the headers).

Ideally, we use the set modifier to make sure that our generated header override any corresponding header coming from the upstream response.

However, we might have the situation where the upstream sends more CORS headers than Couper would generate, e.g. max-age or allow-credentials. In this case we have to actively remove those headers to avoid mixed or unexpected CORS statements.

filex commented 8 months ago

Does the problem only occur with payload requests? The OPTIONS PFR is handled by Couper without actually executing the endpoint, isn't it?

johakoch commented 8 months ago

Does the problem only occur with payload requests? The OPTIONS PFR is handled by Couper without actually executing the endpoint, isn't it?

Yes

johakoch commented 8 months ago

Ideally, we use the set modifier to make sure that our generated header override any corresponding header coming from the upstream response.

We already set them. The problem is not to set it (in contrast to add), it's the right point in the process: The response headers must not be set prior to the nextHandler's ServeHTTP() (as they are, currently), because some next handler will add/set the backend's response headers.

However, we might have the situation where the upstream sends more CORS headers than Couper would generate, e.g. max-age or allow-credentials. In this case we have to actively remove those headers to avoid mixed or unexpected CORS statements.

ACK