Flask로 교차 오리진 리소스 공유 해결


86

다음 ajax게시물 요청에 대해 Flask( 플라스크에서 ajax에서 게시 된 데이터를 어떻게 사용할 수 있습니까? ) :

$.ajax({
    url: "http://127.0.0.1:5000/foo", 
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify({'inputVar': 1}),
    success: function( data ) { 
        alert( "success" + data );
    }   
});

내가 얻을 Cross Origin Resource Sharing (CORS)오류 :

No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'null' is therefore not allowed access. 
The response had HTTP status code 500.

다음 두 가지 방법으로 해결하려고했지만 작동하지 않는 것 같습니다.

  1. Flask-CORS 사용

이것은 교차 출처 AJAX를 가능하게 Flask하는 처리 CORS를 위한 확장입니다 .

이 솔루션을 사용하는 내 pythonServer.py :

from flask import Flask
from flask.ext.cors import CORS, cross_origin

app = Flask(__name__)
cors = CORS(app, resources={r"/foo": {"origins": "*"}})
app.config['CORS_HEADERS'] = 'Content-Type'

@app.route('/foo', methods=['POST','OPTIONS'])
@cross_origin(origin='*',headers=['Content-Type','Authorization'])
def foo():
    return request.json['inputVar']

if __name__ == '__main__':
    app.run()
  1. 특정 플라스크 데코레이터 사용

이것은 장식하는 기능을 허용해야하는 장식자를 정의 하는 공식 Flask 코드 조각 CORS입니다.

이 솔루션을 사용하는 내 pythonServer.py :

from flask import Flask, make_response, request, current_app
from datetime import timedelta
from functools import update_wrapper

app = Flask(__name__)

def crossdomain(origin=None, methods=None, headers=None,
                max_age=21600, attach_to_all=True,
                automatic_options=True):
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    if not isinstance(origin, basestring):
        origin = ', '.join(origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        if methods is not None:
            return methods

        options_resp = current_app.make_default_options_response()
        return options_resp.headers['allow']

    def decorator(f):
        def wrapped_function(*args, **kwargs):
            if automatic_options and request.method == 'OPTIONS':
                resp = current_app.make_default_options_response()
            else:
                resp = make_response(f(*args, **kwargs))
            if not attach_to_all and request.method != 'OPTIONS':
                return resp

            h = resp.headers

            h['Access-Control-Allow-Origin'] = origin
            h['Access-Control-Allow-Methods'] = get_methods()
            h['Access-Control-Max-Age'] = str(max_age)
            if headers is not None:
                h['Access-Control-Allow-Headers'] = headers
            return resp

        f.provide_automatic_options = False
        return update_wrapper(wrapped_function, f)
    return decorator

@app.route('/foo', methods=['GET','POST','OPTIONS'])
@crossdomain(origin="*")
def foo():
    return request.json['inputVar']

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

그 이유를 알려주시겠습니까?


알아 냈어? 나는 똑같은 문제에 부딪혔다 :(
shao dec.

이것은 오래된 질문이지만 확실하게 확인하십시오. Flask 서버를 다시 시작 했습니까? 나는 또한 모든 것이 정확하다고 생각 했는데도 왜 동일한 오류가 발생했는지 궁금했습니다. 알고 보니, 당신 정말 효과 적용하기 위해 서버를 다시 시작
주하 Untinen

답변:


53

코드를 약간 수정 한 후 챔피언처럼 작동했습니다.

# initialization
app = Flask(__name__)
app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy   dog'
app.config['CORS_HEADERS'] = 'Content-Type'

cors = CORS(app, resources={r"/foo": {"origins": "http://localhost:port"}})

@app.route('/foo', methods=['POST'])
@cross_origin(origin='localhost',headers=['Content- Type','Authorization'])
def foo():
    return request.json['inputVar']

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

*를 localhost로 대체했습니다. 많은 블로그와 게시물을 읽었으므로 특정 도메인에 대한 액세스를 허용해야합니다.


2
누군가 청사진을 사용하는 경우 각 청사진에 CORS ()를 추가해야합니다. 예 : my_blueprint = Blueprint ( 'my_bp_name', name , url_prefix = "/ my-prefix") CORS (my_blueprint)
BLang

90

간단한 방법으로 결과를 얻을 수 있습니다.

@app.route('your route', methods=['GET'])
def yourMethod(params):
    response = flask.jsonify({'some': 'data'})
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

1
교차 도메인 구현을 추가하는 것이 더 좋습니다!
Florescu Cătălin 2011

간단하고 효과적인
안토니

4
훌륭한! 동의합니다. 간단하고 효과적입니다. IMO 인정해야 대답
PALEN

3
@Salvador Dali-json 객체 대신 템플릿을 렌더링하는 경우 원본 교차를 허용하는 적절한 방법이 무엇인지 알고 있습니까? 즉, 코드의 마지막 줄은 다음과 yourMethod같습니다.return render_template('template.html',some_var = response)
Matteo

3
게시 방법에 사용할 수 있습니까? 파일 업로드 방법을 시도했지만 실패했습니다.
W.Leto

64

글쎄, 나는 같은 문제에 직면했다. 이 페이지를 방문 할 수있는 신규 사용자를 위해. 공식 문서를 따르십시오.

flask-cors 설치

pip install -U flask-cors

그런 다음 앱 초기화 후 flask-cors기본 인수로 초기화합니다 .

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

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

이 '원점에서'my_domain '에서 XMLHttpRequest의 액세스 나에게 다음과 같은 오류 제공 127.0.0.1:5000 프리 플라이트 요청에 대한 응답은 액세스 제어 검사를 통과하지 않습니다 :'액세스 제어 - Allow- CORS 정책에 의해 차단되었습니다 ' Origin '헤더에' 127.0.0.1:5000 , * ' 값이 여러 개 포함되어 있지만 하나만 허용됩니다.
humblePilgrim

나를 위해 작동하지 않습니다. stackoverflow.com/questions/59652099/…
WP McNeill

나도 Tks를 위해 작동합니다!
Jose

나를 위해 일했습니다! 고마워요 :)
XpressGeek

어떻게 설정 Access-Control-Max-Age을 위해 flask_cors?
DragonKnight

5

이것이 답이 될 수도 있습니다. 나는 오늘 같은 문제가 있었고 예상보다 문제가 많았습니다. CORS 기능을 추가 한 후 코드가 올바른 경우에도 변경 사항을 적용하려면 Flask 서버 ( -> 또는 사용하는 방법)를 다시 시작 해야 합니다. 그렇지 않으면 CORS가 활성 인스턴스에서 작동하지 않습니다.ctrl + cpython manage.py runserver

다음은 제 모습과 작동 방식입니다 (Python 3.6.1, Flask 0.12).

factory.py :

from flask import Flask
from flask_cors import CORS  # This is the magic


def create_app(register_stuffs=True):
    """Configure the app and views"""
    app = Flask(__name__)
    CORS(app)  # This makes the CORS feature cover all routes in the app

    if register_stuffs:
        register_views(app)
    return app


def register_views(app):
    """Setup the base routes for various features."""
    from backend.apps.api.views import ApiView
    ApiView.register(app, route_base="/api/v1.0/")

views.py :

from flask import jsonify
from flask_classy import FlaskView, route


class ApiView(FlaskView):
    @route("/", methods=["GET"])
    def index(self):
        return "API v1.0"

    @route("/stuff", methods=["GET", "POST"])
    def news(self):
        return jsonify({
            "stuff": "Here be stuff"
        })

내 React 앱 console.log에서 :

Sending request:
GET /stuff
With parameters:
null
bundle.js:17316 Received data from Api:
{"stuff": "Here be stuff"}

4

Access-Control-Allow-OriginFlask 응답 객체에 헤더 를 설정하는 것은 대부분의 경우 (이것처럼) 괜찮지 만 정적 자산을 제공 할 때는 영향을 미치지 않습니다 (최소한 프로덕션 설정에서). 정적 자산은 전면 웹 서버 (일반적으로 Nginx 또는 Apache)에서 직접 제공되기 때문입니다. 따라서이 경우 Flask가 아닌 웹 서버 수준에서 응답 헤더를 설정해야합니다.

자세한 내용 은 헤더를 설정하는 방법을 설명하는 이 기사를 참조하십시오 .

또한 @Satu가 말했듯이 JS AJAX 요청의 경우 특정 도메인에 대해서만 액세스를 허용해야 할 수 있습니다. 정적 자산 (예 : 글꼴 파일)을 요청하는 경우 규칙이 덜 엄격하고 모든 도메인에 대한 액세스를 허용하는 것이 더 허용됩니다.


3

저는 Armin Ronacher제공 한 데코레이터 를 약간 수정하여 사용했습니다 (클라이언트가 요청한 다른 헤더로 인해). (애플리케이션 / json 유형을 요청하는 요청자로 angular를 사용하는 곳).

코드는 아래 부분에서 약간 수정되었습니다.

from flask import jsonify

@app.route('/my_service', methods=['POST', 'GET','OPTIONS'])
@crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type'])
def my_service():
    return jsonify(foo='cross domain ftw')

jsonify는 application / json 유형을 보내며 그렇지 않으면 text / html이됩니다. 헤더는 해당 헤더에 대한 내 경우 요청에서 클라이언트로 추가됩니다.

 const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin':'*'
      })
    };
    return this.http.post<any>(url, item,httpOptions)

2
데코레이터에 대한 링크가 죽었
호세의 Tomás Tocino

2

참고 : cross_origin의 위치가 올 바르고 종속성이 설치되어 있어야합니다. 클라이언트 측에서 사용중인 데이터 서버의 종류를 지정해야합니다. 예 : application / json 또는 text / html

나를 위해 아래 작성된 코드는 마술을했습니다.

from flask import Flask,request,jsonify
from flask_cors import CORS,cross_origin
app=Flask(__name__)
CORS(app, support_credentials=True)
@app.route('/api/test', methods=['POST', 'GET','OPTIONS'])
@cross_origin(supports_credentials=True)
def index():
    if(request.method=='POST'):
     some_json=request.get_json()
     return jsonify({"key":some_json})
    else:
        return jsonify({"GET":"GET"})


if __name__=="__main__":
    app.run(host='0.0.0.0', port=5000)

왜 똑같은 일 (support_credentials = True)을 cross_origin합니까?
Eziz Durdyyev

1

이 질문에 늦을 수 있지만 아래 단계에서 문제가 해결되었습니다.

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

0

나는 비슷한 일로 많은 어려움을 겪었습니다. 다음을 시도하십시오.

  1. HTML 헤더를 표시 할 수있는 일종의 브라우저 플러그인을 사용하십시오.
  2. 서비스 URL을 입력하고 반환 된 헤더 값을 확인합니다.
  3. Access-Control-Allow-Origin이 요청 원본이어야하는 단 하나의 도메인으로 설정되어 있는지 확인합니다. Access-Control-Allow-Origin을 *로 설정하지 마십시오.

그래도 도움이되지 않으면이 기사를 살펴보십시오. PHP에 있지만 CORS가 작동하려면 어떤 헤더를 어떤 값으로 설정해야하는지 정확히 설명합니다.

IE, Firefox, Chrome 및 Safari에서 작동하는 CORS

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.