corydolphin / flask-cors

Cross Origin Resource Sharing ( CORS ) support for Flask
https://flask-cors.corydolphin.com/
MIT License
873 stars 140 forks source link

CORS headers not injected when specifying root origins and per-resource origins #248

Open afiorillo opened 5 years ago

afiorillo commented 5 years ago

Hi! I noticed when using the CORS(app, origins=[...], resources={...}) constructor that the origins in the root level are ignore. A simple example application would be

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(
    app,
    origins=["http://localhost:5000"],
    resources={"/a": {"origins": "*"}}
)

@app.route("/a")
def helloWorld():
  return "Hello, cross-origin-world!"

@app.route("/b")
def helloYou():
  return "Hello, localhost!"

app.run(host='localhost', port=5000)

Running this and then using curl, you can see:

If commenting out the resources={...} line then both endpoints have the CORS header, but specific to the localhost origin. Is this intended behavior?

In my particular use case, this came up with an authenticated API (so the origin must not be *) that also contained a swagger.json endpoint that should be public. The idea was that we could make the swagger.json resource served with a * origin, and all other resources served with the listed origins.

afiorillo commented 4 years ago

I had a bit more time to investigate this and found in the documentation:

The settings for CORS are determined in the following order

1. Resource level settings (e.g when passed as a dictionary)
2. Keyword argument settings
3. App level configuration settings (e.g. CORS_*)
4. Default settings

Which led me to a fix for my particular solution, but leaves my original question. My fix initializes the extension with:

CORS(
    app,
    resources={
        "/a": {"origins": "*"},
        # the most general expression at the end
        "/*": {"origins": ["http://localhost:5000"]},
    }
)

Still, the docs would suggest that initializing it in the original way should also work. Should defining a dictionary in resources override the app-level configuration given in other keyword arguments for the extension?