-
-
Notifications
You must be signed in to change notification settings - Fork 971
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Multiple values for access-control-allow-origin #1309
Comments
Doesn't this contradict the very idea of the CORS? it seems to me that it would be better to validate the Origin header on the backend against the list of allowed sources |
Sorry that I don't get what you mean. Do you mean I should not use the cors middleware? In this case we only want the cors header to be sent correctly for all the resources. When I say differences cases, I mean the same origin header in upper and lower cases. |
I did some more experiments and found out the issue is actually coming from calling "MutableHeaders.update()" used in the See the example below: @app.middleware("http")
async def add_cors_header(request: Request, call_next):
response = await call_next(request)
print('==========before====>headers', response.headers)
headers = {"Access-Control-Allow-Credentials": "true"}
response.headers.update(headers)
print('==========after====>headers', response.headers)
return response And this is what I see from the console:
As you can see, for some reason, when we update the headers, it results in both versions: 'Access-Control-Allow-Credentials' and 'access-control-allow-credentials'. |
Merged in #235. Can be closed. |
Hi @aminalaee thanks for looking into it. However it seems #235 is about test client, I don't get why that can fix the issue mentioned here, could you please clarify? |
@oeway Sorry, closed the wrong issue. I'll re-open this. |
I do not think that this is a bug in starlette, but a problem in engineio. It appears that engineio is adding headers without checking for duplicates. In engineio/server.py, one finds the following at line 460:
I will likely take this up with engineio, but the practical fix, at least for me, is to disable CORS handling in socketio by setting cors_allowed_origins=[] when creating the engineio server object. For fastapi-socketio:
I should probably also complain to unicorn for sending multiple response headers with the same name; servers aren't supposed to do this except for Set-Cookie and certain other headers like Vary. |
https://asgi.readthedocs.io/en/latest/specs/www.html#http
|
This is an unfortunate design decision that appears to be based on a misreading of RFC7230. ASGI spec: "Multiple header fields with the same name are complex in HTTP. RFC 7230 states that for any header field that can appear multiple times, it is exactly equivalent to sending that header field only once with all the values joined by commas. However, RFC 7230 and RFC 6265 make it clear that this rule does not apply to the various headers used by HTTP cookies (Cookie and Set-Cookie). The Cookie header must only be sent once by a user-agent, but the Set-Cookie header may appear repeatedly and cannot be joined by commas. The ASGI design decision is to transport both request and response headers as lists of 2-element [name, value] lists and preserve headers exactly as they were provided." RFC 7230: " A sender MUST NOT generate multiple header fields with the same field Not all header fields are defined as comma-separated lists. |
I meant that uvicorn follows ASGI specs, so you should probably "complain" on asgiref. |
Ah. Thanks for the link. |
@declaresub I understand that it's more relevant to fix from the spec and starlette implemented it correctly. However, for practical reasons, do you think we can have a fix in the CORSMiddleware? Instead of blindly add the CORS headers, we should check whether the same header (in different capitalization) exists already. What do you think? |
For this particular issue, the fix needed is to use exactly one of starlette or engine.io to handle CORS, as noted earlier. I haven't gone through cors.py as carefully as I could, but I didn't see any place where headers were being appended. Perhaps it would be useful to make sure that it overwrites any existing headers that it sets. The real solution to sloppy middleware is, of course, more middleware. I have it in mind to write some header middleware that checks for multiple headers with the same name, and does something when such are found. I don't believe this can be done reliably in starlette, because middleware can always be added outside the control of starlette. |
If that's the case, I don't think we have an issue on Starlette. |
I don't think it makes sense for the Given the statement above:
I'm closing the issue. If you think this is not solved, or there's a different point of view that was not presented, feel free to express yourself here, in a new issue, or reach out to us on our Gitter channel. |
I mailed you, so that i don't have to reopen this, but I am having a weird behavior here,
everytime i add a single CORS middleware origin, I grepped, its the only call, it adds two and yields the known bug. Any suggestion? |
This should do: #1309 (comment) |
Please explain as if I was retarded. (Sorry, spent a night.) =) |
I mean, you are using python-socketio, right? |
FastAPI with uvicorn |
Can you share a minimal reproducible example? |
https://github.com/lyrasadie/lyra-api/blob/main/api/__init__.py When not commented out, 2 CORS headers. When, none. |
https://github.com/lyrasadie/lyra-api/blob/main/api/__init__.py When not commented out, 2 CORS headers. When, none. Aware of the missing [ ] in comment |
@zdanl did you ever figure this out? |
i stuck into the same problem. origins = [ is there any workaround for this? |
Checklist
master
.Describe the bug
When using starlette (through FastAPI) CORSMiddleware with python-socketio (another ASGI app mounted via app.mount()), I got multiple values for the access-control-allow-origin headers. This is because both python socketio and the CORSMiddleware will inject CORS headers in different cases. In the response I see two duplicated headers:
And the browser complain it as a CORS error.
To reproduce
Expected behavior
The CORSMiddleware should check existing headers in different cases and update them only if the headers in different cases not exists.
Actual behavior
The CORSMiddleware add the cors haders and result in multiple duplicated values.
Environment
Additional context
The text was updated successfully, but these errors were encountered: