Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix allow_cors: true returning two Access-Control-Allow-Origin headers #489

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

matthieugouel
Copy link

@matthieugouel matthieugouel commented Dec 1, 2024

Description

Fixes #93.
The Access-Control-Allow-Origin was set before on the response before the proxy call, and ClickHouse was returning the response with its own Access-Control-Allow-Origin (in my case, "*"). So, having allow_cors: true was eventually returning two Access-Control-Allow-Origin, one from chproxy and one from ClickHouse.

This commit just move the "Access-Control-Allow-Origin after the proxy call, overriding the value returned by ClickHouse. If allow_cors: false, chproxy does not change the value (so it can be, I believe, any value set by ClickHouse), else, with allow_cors: true, it will override to either the value of Origin request if any or else *.

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

Checklist

  • Linter passes correctly
  • Add tests which fail without the change (if possible)
  • All tests passing
  • Extended the README / documentation, if necessary

Does this introduce a breaking change?

  • Yes
  • No

Further comments

The only thing I'm not sure is if we want to pass the initial Access-Control-Allow-Origin that was set originally.
But in my understanding of the feature, the goal is not to add this header to the proxied request to ClickHouse, but rather on the chproxy response.

@vfoucault
Copy link
Collaborator

vfoucault commented Dec 2, 2024

Hi there and thanks for your contribution.

I honestly don't believe that cors, moved from line 110 to 144 will not have any effect.
Response is handled in that block

if shouldReturnFromCache {
		rp.serveFromCache(s, srw, req, origParams, q)
	} else {
		rp.proxyRequest(s, srw, srw, req)
	}

Adding a header after doesn't seems to have any effect since the WriteHeader would already have occurred in io.go line 71.

I don't have any idea right now on how to handle this. best would be to open an issue, and feel free to propose a solution for this issue as well.

thanks

@matthieugouel
Copy link
Author

matthieugouel commented Dec 2, 2024

Hey,

Without any change, a call with to chproxy with Origin header (set to localhost:1234) and allow_origin: true option will result with those response headers:

< HTTP/2 200
< access-control-allow-headers: origin, x-requested-with, x-clickhouse-format, x-clickhouse-user, x-clickhouse-key, Authorization
< access-control-allow-methods: POST, GET, OPTIONS
< access-control-allow-origin: localhost:1234
< access-control-allow-origin: *
< access-control-max-age: 86400
< alt-svc: h3=":443"; ma=2592000
< content-type: text/tab-separated-values; charset=UTF-8
< date: Mon, 02 Dec 2024 16:39:23 GMT
< server: Caddy
< x-clickhouse-format: TabSeparated
< x-clickhouse-query-id: 180D6993B76A406F
< x-clickhouse-server-display-name: cc2ee7e84a61
< x-clickhouse-summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","result_rows":"0","result_bytes":"0","elapsed_ns":"4444212"}
< x-clickhouse-timezone: UTC
< content-length: 0
<

You can notice the duplicate access-control-allow-origin that the issue #93 is referring to.

When doing the same test with the change of this PR (no config change), we have the following response headers:

< HTTP/2 200
< access-control-allow-headers: origin, x-requested-with, x-clickhouse-format, x-clickhouse-user, x-clickhouse-key, Authorization
< access-control-allow-methods: POST, GET, OPTIONS
< access-control-allow-origin: localhost:1234
< access-control-max-age: 86400
< alt-svc: h3=":443"; ma=2592000
< content-type: text/tab-separated-values; charset=UTF-8
< date: Mon, 02 Dec 2024 16:46:11 GMT
< server: Caddy
< x-clickhouse-format: TabSeparated
< x-clickhouse-query-id: 180D69FCF89CFE24
< x-clickhouse-server-display-name: cc2ee7e84a61
< x-clickhouse-summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","result_rows":"0","result_bytes":"0","elapsed_ns":"4273178"}
< x-clickhouse-timezone: UTC
< content-length: 0
<

As you can see we have only one access-control-allow-origin corresponding to the Origin.

To finish we can do the same test without the origin on the PRs's version:

< HTTP/2 200
< access-control-allow-origin: *
< alt-svc: h3=":443"; ma=2592000
< content-type: text/tab-separated-values; charset=UTF-8
< date: Mon, 02 Dec 2024 16:47:43 GMT
< server: Caddy
< x-clickhouse-format: TabSeparated
< x-clickhouse-query-id: 180D69FCF89CFE25
< x-clickhouse-server-display-name: cc2ee7e84a61
< x-clickhouse-summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","result_rows":"0","result_bytes":"0","elapsed_ns":"4530191"}
< x-clickhouse-timezone: UTC
< content-length: 0
<

Which is the same result as without the change, ie. only one access-control-allow-origin set as *.

The change works because it will update the access-control-allow-origin chproxy response after the header change made by the proxified response from ClickHouse. This proxified response adds its own access-control-allow-origin, so if chproxy add access-control-allow-origin before, you will end up with two times the header.
Conversely, updating this header after the proxified response will override ClickHouse access-control-allow-origin header and so you will always end up with only 1 header.

@mga-chka
Copy link
Collaborator

lgtm, we should release a new version including your fix in 1-2 weeks (we first need to validate and merge the other active PRs)

@mga-chka
Copy link
Collaborator

I was a bit in a rush in my "looks good to me". Since the bug is tricky and could reappear after a refactoring, can you add a test in main_test.go?

…eaders

Fixes ContentSquare#93.
The `Access-Control-Allow-Origin` was set before on the response before the proxy call,
and ClickHouse was returning the response with its own `Access-Control-Allow-Origin` (in my case, "*").
So, having `allow_cors: true` was eventually returning two `Access-Control-Allow-Origin`, one from chproxy and one from ClickHouse.

This commit just move the `"Access-Control-Allow-Origin` after the proxy call, overriding the value returned by ClickHouse.
If `allow_cors: false`, chproxy does not change the value (so it can be, I believe, any value set by ClickHouse), else, with `allow_cors: true`,
it will override to either the value of `Origin` request if any or else `*`.
@matthieugouel
Copy link
Author

Hey @mga-chka! Thanks for looking at this.
I added some tests but unfortunately they do not work for now. For some reasons I don't get the test response does not contains the headers set by the proxy. So the tests I've added never contain Access-Control-Allow-Origin.

Would you have an idea of why?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

allow_cors may break CORS
3 participants