corydolphin / flask-cors

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

Flask-Cors not working while using url_prefix in blueprints #289

Closed amandesai01 closed 2 years ago

amandesai01 commented 3 years ago

I was using flask-cors for my flask application which failed to enable CORS for blueprints where blueprints were registered along with url_prefix as their property. However, when I removed url_prefix and manually added prefix in blueprints, CORS seemed to be working fine.

Example

This code works properly

from flask import Flask, make_response
from flask_cors import CORS

from tracer.blueprints.auth import app as auth_blueprint
from tracer.blueprints.url import app as url_blueprint

app = Flask(__name__)
CORS(app)

app.register_blueprint(auth_blueprint)
app.register_blueprint(url_blueprint)

if __name__ == '__main__':
    app.run(host='0.0.0.0')

This code doesn't allow CORS

.
.
app.register_blueprint(auth_blueprint, url_prefix='/auth')
app.register_blueprint(url_blueprint, url_prefix='/url')
.
.
nejat-njonjo commented 3 years ago

I was facing the same issue but the error was generated by undefined variables etc. Also in the frontend I set withCredentials to true.

Try this:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

CORS(app, resources={r'/*': origins: '*'})

With credentials

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

CORS(app,
  resources={r'/*': origins: '*'},
  supports_credentials=True
)
aalokrmb commented 3 years ago

I am facing the same issue, can anyone please tell me how to resolve it?

amandesai01 commented 3 years ago

@aalokrmb I know my solution is not good, but this was a proper workaround for me. Don't provide url_prefix while registering blueprint and everything will work fine.

PhilipRead commented 2 years ago

Just thought I'd throw my perspective. I was having the same issue and I could not for the life of me understand why some calls were getting CORS errors. Upon closing inspection I realized that the 'bad' urls where returning 308s. After looking at the Location header I realized that it was failing because my blueprint routes for those failing endpoints had trailing slashes in them. Once I took them out it all worked fine. Why Axios or Chrome can't just process the redirect instead of failing with a misleading 'CORS' issue is beyond me.

Anyway, here is an example of what I mean:

bp = Blueprint('api', __name__, url_prefix = '/api')

# @bp.route('some-resources/', methods = ('GET', 'POST')) # Wrong
@bp.route('some-resources', methods = ('GET', 'POST')) # Right!
def someResources():
...
gianlukk994 commented 2 years ago

Defining url_prefix inside Blueprint constructor works.

#app.py 
from flask_cors import CORS
CORS(app, resources={r'/*': {'origins': '*'}})

app.register_blueprint(stocks_bp)
#blueprint 
stocks_bp = Blueprint('stocks_bp', __name__, url_prefix='/stocks')

Btw it's strange, hope they fix it.

Njima1572 commented 2 years ago

I was having similar issue, for me it was the trailing slash

# ============== app.py =============== 
from flask_cors import CORS
CORS(app, resources={r'/*': {'origins': '*'}})

app.register_blueprint(blue_print_realestate, url_prefix='/api/v1/realestates')

# ========== realestates.py ==============
blueprint_realestate = Blueprint(
  name='realestates', import_name=__name__
)

@blueprint_realestate.route("", methods=["POST"]) # <- I had it as "/" instead and was appended apparently
def post_realestate():
   # whatever stuff

I hope this solves some of the problems Not sure about the side effect of having blank endpoint for @bp.route part, so might be better to have something up there.

In my case, I assume that the trailing slash led the redirect with OPTIONS method and that seemed like what was causing problems.

nejat-njonjo commented 2 years ago

This issue has to be closed now. A lot of solutions have come forward.

aalokrmb commented 2 years ago

This issue has to close now. A lot of solutions have come forward.

yup, we can close it, thanks to everyone for your help and suggestions, However, the @gianlukk994 solution worked fine for me. thanks, @gianlukk994.

amandesai01 commented 2 years ago

Yes sure. Lot of solutions have come up. So, here are final work arounds:

  1. https://github.com/corydolphin/flask-cors/issues/289#issuecomment-926371319
  2. https://github.com/corydolphin/flask-cors/issues/289#issuecomment-879969094

Closing this issue now.

Jerakin commented 2 years ago

I am having issues getting flask cors work for me too. I am using flask-restx as my rest helper.

I am using Namespace from restx (their version of bluebrints).

from flask_restx import Namespace, Resource
...
ns = Namespace(name='api_v1', path="/api/v1")

@ns.route('/section/<string:url_id>')
class Section(Resource):
    def put(self, url_id):
        print("Do some Put work")
        return None, 201

and I am trying to enable cors on the api end points

CORS(app, resources={r"/api/*": {"origins": "*"}})

This is what's trying to call

$.ajax({
    type: 'PUT',
    crossDomain: true,
    url: the_url_here,
    contentType: 'application/json',
    data: {"type": "value"},
})

Am I doing something odd here? Can someone see a fix for it? Have anyone had any luck with flask-cors and flask-restx together?

nejat-njonjo commented 2 years ago

There are a lot of solutions on this thread. Try all of them before posting. This issue must be closed now, please.

When you allow all origins (*) make sure you have credentials turned off in your request otherwise specify the origins.

This is how I always set up a flask server.

from flask import Flask
from flask_cors import CORS

from .api import v1_routes

def create_app():
    app = Flask(__name__)

    # Cross Origin Settings
    cors_origin = [
        'http://192.168.0.27:4200',
        'http://localhost:4200'
    ]

    CORS(
        app,
        resources={r"/api/*": {"origins": cors_origin}},
        supports_credentials=True,
    )

    with app.app_context():
        app.register_blueprint(v1_routes.router, url_prefix='/api/v1')

    return app

Then in your request headers add

{
    "withCredentials": true
}

If it doesn't work, Let me know.

marlon-rt14 commented 1 year ago

flask-cors works with nested blueprints, just ensure a path doesn't have slash. for example

NOT WORKING @router("/", methods=['GET']) def get_data():

WORKING @router("", methods=['GET']) def get_data():

@router("/list", methods=['GET']) def get_data():

@router("/", methods=['GET']) def get_data():