Flask RESTful cross-domain issue with Angular: PUT, OPTIONS methods

前端 未结 9 1107
臣服心动
臣服心动 2020-12-12 17:14

I\'ve developed a small write-only REST api with Flask Restful that accepts PUT request from a handful of clients that can potentially have changing IP addresses. My clients

相关标签:
9条回答
  • 2020-12-12 17:38

    I like to use a decoration to solve.

    def cross_origin(origin="*"):
        def cross_origin(func):
            @functools.wraps(func)
            def _decoration(*args, **kwargs):
                ret = func(*args, **kwargs)
                _cross_origin_header = {"Access-Control-Allow-Origin": origin,
                                        "Access-Control-Allow-Headers":
                                            "Origin, X-Requested-With, Content-Type, Accept"}
                if isinstance(ret, tuple):
                    if len(ret) == 2 and isinstance(ret[0], dict) and isinstance(ret[1], int):
                        # this is for handle response like: ```{'status': 1, "data":"ok"}, 200```
                        return ret[0], ret[1], _cross_origin_header
                    elif isinstance(ret, basestring):
                        response = make_response(ret)
                        response.headers["Access-Control-Allow-Origin"] = origin
                        response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"
                        return response
                    elif isinstance(ret, Response):
                        ret.headers["Access-Control-Allow-Origin"] = origin
                        ret.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"
                        return ret
                    else:
                        raise ValueError("Cannot handle cross origin, because the return value is not matched!")
                return ret
    
            return _decoration
    
        return cross_origin
    

    And then, Use decoration in your restful api.

    class ExampleRestfulApi(Resource)
        @cross_origin()
        def get(self):
            # allow all cross domain access
            pass
    
        @cross_origin(origin="192.168.1.100")
        def post(self):
            # allow 192.168.1.100 access
            pass
    
    0 讨论(0)
  • 2020-12-12 17:43

    Just an update to this comment. Flask CORS is the way to go, but the flask.ext.cors is deprecated.

    use: from flask_cors import CORS

    0 讨论(0)
  • 2020-12-12 17:43

    To allow remote CORS requests on your web service api, you can simply initialize your flask restful API like this:

    from flask import Flask
    from flask_restful import reqparse, abort, Api, Resource
    from flask_cors import CORS
    
    app = Flask(__name__)
    cors = CORS(app, resources={r"*": {"origins": "*"}})
    api = Api(app)
    

    This adds the CORS header to your api instance and allows a CORS request on every path from every origin.

    0 讨论(0)
  • 2020-12-12 17:49

    I was facing the multiple types of CORS issue while connecting to my flask rest api from angular and tried almost all the approaches.
    If you want to give access to all the websites without any restriction you can add below code in you app.py script :

    from flask_cors import CORS , cross_origin
    
    cors = CORS(app, resources={r"/*": {"origins": "*"}})
    

    this will work, but its recommended to have some security which you can always edit in origin

    0 讨论(0)
  • 2020-12-12 17:53

    You're right, OPTIONS method called every time before real request in browser. OPTIONS response have allowed methods and headers. Flask automatically process OPTIONS requests.

    To get access for cross domain request you API must have Access-Control-Allow-Origin header. It can contain specific domains, but if you want allow requests from any domains you can set it to Access-Control-Allow-Origin: *.

    To set up CORS for flask you can look at one extension code or try use this extension: https://github.com/wcdolphin/flask-cors/blob/master/flask_cors.py.

    To set up CORS for flask-restful look this pull requests: https://github.com/twilio/flask-restful/pull/122 and https://github.com/twilio/flask-restful/pull/131. But looks like flask-restful does not support it by default yet.

    0 讨论(0)
  • 2020-12-12 17:56

    How about this workaround:

    from flask import Flask
    from flask.ext import restful
    from flask.ext.restful import Api
    from flask.ext.sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    app.config.from_object('config')
    
    #flask-sqlalchemy
    db = SQLAlchemy(app)
    
    #flask-restful
    api = restful.Api(app)
    
    @app.after_request
    
    def after_request(response):
      response.headers.add('Access-Control-Allow-Origin', '*')
      response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
      response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
      return response
    
    import views
    

    I took this from this tutorial. Works very good. actually, i think this is the best approach I've seen so far.

    Returning {'Access-Control-Allow-Origin': '*'} on each endpoint, doesn't seems to be efficient since you have to add it on every endpoint. a bit anoying..., at least for me.

    I tried @cors.crossdomain(origin='*') but, looks like it only works with GET request.

    0 讨论(0)
提交回复
热议问题