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

How to resolve multiple CORS values in socketio requests, Sanic? #205

Closed
RuWander opened this issue Oct 9, 2018 · 17 comments
Closed

How to resolve multiple CORS values in socketio requests, Sanic? #205

RuWander opened this issue Oct 9, 2018 · 17 comments
Assignees
Labels

Comments

@RuWander
Copy link

RuWander commented Oct 9, 2018

Hi,
I am having trouble with CORS in python-socketio. I have built a Restful API in Sanic and I am consuming the API with Angular 6. I have added socketio functionality with Python-socketio, however, I am receiving the following error in the browser:
Failed to load http://192.168.33.11:7770/socket.io/?EIO=3&transport=polling&t=MPP6E-6: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:4200, http://localhost:4200', but only one is allowed. Origin 'http://localhost:4200' is therefore not allowed access.

It seems to be adding two origins to the Access-Control-Allow-Origin header.
python-socketio

I have tried setting the cors_allowed_origins to a list containing the http://localhost:4200 but that did not work.

I also had to install the Sanic_Cors (https://github.com/ashleysommer/sanic-cors) module in order to allow CORS for the normal API routes. If I remove the CORS(app) from the below configuration the socket connections seem to be working.

My server currently looks like this:
sio = socketio.AsyncServer(async_mode='sanic', cors_credentials=True)
app = Sanic()
app.config['CORS_AUTOMATIC_OPTIONS'] = True

sio.attach(app)
CORS(app)

Is there a way to have these two modules work in harmony, or to fix the origin header in the Socketio module?

I hope you can help me.
I appreciate any help in advance!
Thanks!

@miguelgrinberg
Copy link
Owner

I'll have to check this, but it appears that Sanic is reporting the origin sent by the client two times in a row. Not sure if there is some sort of collision with the sanic-cors package or if it is something else, but that seems to be the root cause.

@RuWander
Copy link
Author

Hi, thank you for the quick response.
I have found a workaround to this issues if anyone else runs into it, I can use the @cross_origin(app) decorator on each of the API routes, and it will fix the CORS issues without reporting to the client twice. Meaning the socket routes will work as intended.

It might be obvious in retrospect but the order of placement of the decorator, however, was important in my case as I have @authorized() decorator that handles tokens and other user related queries. This was why the decorator did not work at first in my case and was giving errors. So my working code looks like this:
@app.route('/some_route', methods=['POST'])
@cross_origin(app)
@authorized()
async def some_route(request, user):
# do some work and send return response

The @cross_origin(app) should run before the @authorized() in order for my authorize function to work.

@python-programmer
Copy link

+1
I have the same problem, too
@RuWander I did not understand your solution.
The question was about python-socketio - multiple value for Access-Control-Allow-Origin
But the answer, was the sanic handler.

@ali9itani
Copy link

Thank you @RuWander , your solution worked perfectly

@ali9itani
Copy link

+1
I have the same problem, too
@RuWander I did not understand your solution.
The question was about python-socketio - multiple value for Access-Control-Allow-Origin
But the answer, was the sanic handler.

In sanic, the cors was applied to all connections, even if the socketio connections has there own cors settings set. So there was a duplicate values one from the socketio default and one from the sanic_cors.
By using the sanic cors only on the functions not related to socketio, the things get to normal and no more duplicate values for socketio connections.
So @python-programmer you need to separate things in your app as @RuWander did.

@miguelgrinberg
Copy link
Owner

miguelgrinberg commented Feb 16, 2019

I was just looking at this issue (sorry for taking so long!).

Since you guys have CORS set up on the Sanic side, wouldn't it make sense to disable CORS support on the Socket.IO side? You can do that by passing cors_allowed_origins=[] in your SocketIO constructor. This will disable any efforts from the Socket.IO on setting CORS related headers.

Let me know if that works!

@rajezvelse
Copy link

@miguelgrinberg I tried by setting cors_allowed_origins=[]. But it couldn't help. The error is

The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'

I have also tried setting cors_credentials. Couldn't help. @RuWander 's workaround is helped to resolve this.

@miguelgrinberg
Copy link
Owner

I finally spent some time investigating this issue.

A working Sanic configuration when using the sanic-cors extension is below:

app.config['CORS_AUTOMATIC_OPTIONS'] = True
app.config['CORS_SUPPORTS_CREDENTIALS'] = True

On the Socket.IO side, the server must be initialized to not do anything related to CORS:

eio = engineio.AsyncServer(async_mode='sanic', cors_allowed_origins=[])

With this configuration, CORS is 100% controlled by Sanic. Hope this helps.

@miguelgrinberg
Copy link
Owner

The above has been added to the documentation.

@salimaboubacar
Copy link
Contributor

@miguelgrinberg I am under the impression that this workaround is broken since the latest release of python-engineio (miguelgrinberg/python-engineio@7548f70). I haven't had time to investigate deeper yet, but this is the only thing that seemed to have changed in the last days

@miguelgrinberg
Copy link
Owner

miguelgrinberg commented Jul 31, 2019

@salimaboubacar It's not that it broke, python-engineio had to be changed to address security issues with the WebSocket protocol. If you want the old behavior, you can add cors_allowed_origins='*' to your SocketIO() object.

@salimaboubacar
Copy link
Contributor

In general yes, unfortunately, doing that reproduces the exact symptoms of this issue (multiple values for Access-Control-Allow-Origin)

@miguelgrinberg
Copy link
Owner

Yes, I just tested it here and you are correct, using cors_allowed_origins=[] does not work like it used to. I'll fix it.

@miguelgrinberg
Copy link
Owner

@salimaboubacar can I ask you to test the master branch of python-engineio? Let me know if the problem is addressed with this fix or not.

@salimaboubacar
Copy link
Contributor

Sure, will do tomorrow :)

@dbrnz
Copy link
Contributor

dbrnz commented Jun 20, 2020

In case others struggle to get things working, I've just had what appears to be exactly this issue using Sanic which was finally solved by specifying transports when creating the client socket:

const socket = io('http://localhost:4329', {
     transports: ['websocket', 'polling', 'flashsocket']
)};

as discussed here.

BTW this was with Chrome; FF didn't have these issues.

@inactivist
Copy link

inactivist commented Dec 13, 2020

In case others struggle to get things working, I've just had what appears to be exactly this issue using Sanic which was finally solved by specifying transports when creating the client socket:

const socket = io('http://localhost:4329', {
     transports: ['websocket', 'polling', 'flashsocket']
)};

as discussed here.

BTW this was with Chrome; FF didn't have these issues.

(Dropping this here in case this helps others)

I was experiencing exactly this symptom using fastapi-socketio - multiple access-control-allow-origin header entries in the FastAPI server response. Chrome complains about errors and doesn't upgrade; FireFox does not.

fastapi-socketio hardwires async_mode="asgi" in the AsyncServer constructor.

I applied @dbrnz's transports quick fix shown above, which helped me move past this problem for now. When time permits I'll investigate a proper fix...

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

No branches or pull requests

8 participants