ashleysommer / sanic-cors

A Sanic extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible. Based on flask-cors by Cory Dolphin.
MIT License
159 stars 22 forks source link

Setting up CORS for multiple domains #46

Open smlbiobot opened 4 years ago

smlbiobot commented 4 years ago

Per Mozilla docs there can only be one Access-Control-Allow-Origin header present.

To limit access to specific domains, nginx allows you to regex test the incoming host and to match it in the header:

f ($http_origin ~* "^https?://dev\.example\.com$" ) {
    add_header Access-Control-Allow-Origin $http_origin;
}

How would I go about doing this with this library? I’ve tried putting a list of domains in the origins keyword, as suggested in the Flask-CORS docs but it simply uses the first value in the list.

ashleysommer commented 4 years ago

Hi @smlbiobot Sorry I'm having trouble following your question. Seems like you have three different points?

Per Mozilla docs there can only be one Access-Control-Allow-Origin header present.

Correct. If Sanic-CORS is adding more than one, that is a bug. Please file an issue about that.

To limit access to specific domains, nginx allows you to regex test the incoming host and to match it in the header.

Can you rephrase that in a different way? Do you mean nginx checks the HTTP Host header in the Request, and adds it to the Access-Control-Allow-Origin header in the response? Generally a HTTP 'Host' is a different concept than a CORS 'Origin', careful not to confuse them.

How would I go about doing this with this library? I’ve tried putting a list of domains in the origins keyword, as suggested in the Flask-CORS docs

Sanic-CORS is a direct port from Flask-CORS, so most of the documentation from Flask-CORS should still apply to Sanic-CORS, including that for the list of valid origins. The test suite still passes for that feature, so should still work as per the documentation.

it simply uses the first value in the list

That might be a bug, one which may not be picked up by the test suite. I can try to reproduce it and let you know.

smlbiobot commented 4 years ago

Hi @ashleysommer let me explain what I needed. The way I understand how the Access-Control-Allow-Origin header works is that you can’t specific multiple domains to it, but that it is suggested the server adding the header could simply respond to the request by allowing the specific domain depending on where the request is coming from.

Sample code:

cors = CORS(
    app,
    resources={
        r"/static/*": {
            "origins": [
                "https://example.com",
                "https://subdomain.example.com",
                "https://subdomain2.example.com",
            ]
        }
    },
    methods=['GET'],
)

Expected behavior: Depending on which domain is requesting the resource, it should add these headers:

example.com is requesting:

Access-Control-Allow-Origin: https://example.com

subdomain.example.com is requesting:

Access-Control-Allow-Origin: https://subdomain.example.com

random.com is request: No header is added.

When I am using this library right now, it always returns the first domain. So e.g. when I request from subdomain.example.com, I get this header:

Access-Control-Allow-Origin: https://example.com

Needless to say, that resulted in me not being able to use the resource.

Also if it’s important, I am testing this on localhost only, but setting up multiple localhost hostname e.g.:

dev.local
localhost

and I can see even if I had added both to the origins, that only the first item in the list ever gets return.

rhazz commented 4 years ago

same need.

ashleysommer commented 4 years ago

Ok, this might be caused by something in the porting process between Flask-CORS and Sanic-CORS. Just surprising that the test-suite doesn't pick this up. I don't have any time to investigate it or make a fix, but certainly can review and accept pull-requests.