फ्लास्क के साथ क्रॉस ओरिजिनल रिसोर्स शेयरिंग को हल करें


87

निम्नलिखित ajaxपोस्ट अनुरोध के लिए Flask( मैं फ्लास्क में अजाक्स से पोस्ट किए गए डेटा का उपयोग कैसे कर सकता हूं? ):

$.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 को संभव बनाना चाहिए।

मेरे 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. विशिष्ट फ्लास्क डेकोरेटर का उपयोग करना

यह एक आधिकारिक फ्लास्क कोड स्निपेट है जो एक डेकोरेटर को परिभाषित करता है जिसे 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()

क्या आप कृपया कुछ संकेत दे सकते हैं कि ऐसा क्यों है?


क्या आपने पता लगाया? मैं ठीक उसी मुद्दे पर चलता हूं :(
शाओ

यह एक पुराना सवाल है, लेकिन सिर्फ यह सुनिश्चित करने के लिए: क्या आपने अपना फ्लास्क सर्वर फिर से शुरू किया है? मैं यह भी सोच रहा था कि मुझे वही त्रुटि क्यों मिली, यहां तक ​​कि सब कुछ ठीक वैसा ही था जैसा उन्हें होना चाहिए था। पता चला है, तुम हो क्रम में सर्वर को पुनः आरंभ करने यह वास्तव में प्रभावी करने के लिए
जुहा 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()

मैंने लोकलहोस्ट द्वारा * प्रतिस्थापित किया। चूंकि मैं कई ब्लॉगों और पोस्टों में पढ़ता हूं, इसलिए आपको विशिष्ट डोमेन तक पहुंचने की अनुमति देनी चाहिए


2
यदि कोई ब्लूप्रिंट का उपयोग कर रहा है, तो आपको प्रत्येक ब्लूप्रिंट को CORS () जोड़ना होगा, उदाहरण के लिए: my_blueprint = ब्लूप्रिंट ('my_bp_name', नाम , url_prefix = "/ my-prefix") CORS (my_blueprint)
BLang

91

आप एक सरल के साथ परिणाम प्राप्त कर सकते हैं:

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

1
बेहतर है कि क्रॉसडोमेन कार्यान्वयन जोड़ना!
फ्लेयर्सक्यू कैटेलीन

1
सरल और प्रभावी
एंथनी

5
प्रतिभाशाली! मैं सहमत हूं, सरल और प्रभावी। IMO का उत्तर स्वीकार किया जाना चाहिए
PALEN

3
@ साल्वाडोर डाली - क्या आप जानते हैं कि अगर मैं सिर्फ एक जोंस ऑब्जेक्ट के बजाय एक टेम्पलेट प्रदान कर रहा हूं तो क्रॉस ओरिजिन को अनुमति देने का उचित तरीका क्या है? कोड की अंतिम पंक्ति IE में yourMethodहै:return render_template('template.html',some_var = response)
Matteo

3
क्या यह एक पोस्ट विधि में इस्तेमाल किया जा सकता है? मैंने फ़ाइल अपलोड विधि के लिए प्रयास किया और मैं विफल रहा।
डब्ल्यू.ल्टो १४'१

64

खैर, मैंने उसी मुद्दे का सामना किया। नए उपयोगकर्ताओं के लिए जो इस पृष्ठ पर उतर सकते हैं। बस उनके आधिकारिक दस्तावेज का पालन करें।

फ्लास्क-कोर्स स्थापित करें

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' पर उत्पत्ति से ' 127.0.0.1.1000 ' को CORS नीति द्वारा अवरुद्ध कर दिया गया है: पूर्व-अनुरोध अनुरोध का उत्तर एक्सेस कंट्रोल चेक पास नहीं करता है: 'एक्सेस-कंट्रोल-अनुमति' उत्पत्ति 'शीर्षक में कई मान' 127.0.0.1 .000 , * 'शामिल हैं, लेकिन केवल एक की अनुमति है।
विनम्रप्रीलिम

मेरे लिए काम नहीं करता है। stackoverflow.com/questions/59652099/…
WP McNeill

मेरे लिए भी काम करता है Tks!
जोस

मेरे लिए काम किया! बहुत बहुत धन्यवाद :)
XpressGeek

कैसे स्थापित करने के लिए Access-Control-Max-Ageके लिए flask_cors?
ड्रैगनकेटर सेप 18'20

5

साथ ही इसका उत्तर दे सकते हैं। मेरे पास आज भी यही मुद्दा था और यह उम्मीद से ज्यादा गैर-मुद्दा था। कॉर्स कार्यक्षमता को जोड़ने के बाद, आपको परिवर्तन को प्रभावी करने के लिए अपने फ्लास्क सर्वर ( -> , या जो भी उपयोग की गई विधि) को पुनः आरंभ करना होगा , भले ही कोड सही हो। अन्यथा कॉर्स सक्रिय उदाहरण में काम नहीं करेगा।ctrl + cpython manage.py runserver

यह मेरे लिए कैसा दिखता है और यह काम करता है (पायथन 3.6.1, फ्लास्क 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"
        })

मेरे रिएक्ट ऐप में कंसोल .log:

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

4

ध्यान दें कि Access-Control-Allow-Originफ्लास्क रिस्पांस ऑब्जेक्ट में हेडर सेट करना कई मामलों में ठीक है (जैसे कि यह एक), लेकिन स्थिर संपत्ति (उत्पादन सेटअप में, कम से कम) परोसते समय इसका कोई प्रभाव नहीं पड़ता है। ऐसा इसलिए है क्योंकि स्थैतिक संपत्ति सीधे सामने वाले वेब सर्वर (आमतौर पर Nginx या Apache) द्वारा दी जाती है। तो, उस स्थिति में, आपको वेब सर्वर स्तर पर प्रतिक्रिया शीर्षलेख सेट करना होगा, फ्लास्क में नहीं।

अधिक जानकारी के लिए, यह लेख देखें जिसे मैंने कुछ समय पहले लिखा था, यह बताते हुए कि हेडर कैसे सेट करें (मेरे मामले में, मैं फ़ॉन्ट विस्मयकारी परिसंपत्तियों की क्रॉस-डोमेन सेवारत करने की कोशिश कर रहा था)।

इसके अलावा, जैसा कि @Satu ने कहा, आपको JS AJAX के अनुरोधों के मामले में केवल एक विशिष्ट डोमेन के लिए उपयोग की अनुमति देने की आवश्यकता हो सकती है। स्थैतिक संपत्ति (जैसे फ़ॉन्ट फ़ाइलें) का अनुरोध करने के लिए, मुझे लगता है कि नियम कम सख्त हैं, और किसी भी डोमेन के लिए उपयोग की अनुमति अधिक स्वीकार्य है।


3

मैंने अर्मिन रोनाचेर द्वारा दिए गए डेकोरेटर को थोड़े संशोधनों (क्लाइंट द्वारा अनुरोध किए गए विभिन्न हेडर के कारण) के साथ इस्तेमाल किया। और जो मेरे लिए काम करते थे। (जहां मैं आवेदन / json प्रकार अनुरोधकर्ता के रूप में कोणीय का उपयोग करता हूं)।

कोड को नीचे के स्थानों पर थोड़ा संशोधित किया गया है,

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 एक एप्लीकेशन / json टाइप भेजेगा, अन्यथा यह टेक्स्ट / html होगा। हेडर उन हेडर के लिए मेरे मामले अनुरोध में ग्राहक के रूप में जोड़े जाते हैं

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

2
डेकोरेटर का लिंक मर चुका है
जोस टॉमस टोसिनो

2

नोट: cross_origin का प्लेसमेंट सही होना चाहिए और निर्भरताएं स्थापित की गई हैं। क्लाइंट की ओर, यह निर्दिष्ट करना सुनिश्चित करें कि किस प्रकार का डेटा सर्वर उपभोग कर रहा है। उदाहरण के लिए आवेदन / json या पाठ / 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?
एज़िज़ दुरयदेव

1

मुझे इस सवाल पर देर हो सकती है लेकिन नीचे दिए गए चरणों ने इस मुद्दे को तय किया

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

0

मैंने कुछ इसी तरह का संघर्ष किया। निम्नलिखित का प्रयास करें:

  1. कुछ प्रकार के ब्राउज़र प्लगइन का उपयोग करें जो HTML हेडर प्रदर्शित कर सकते हैं।
  2. अपनी सेवा में URL दर्ज करें, और लौटे हेडर मूल्यों को देखें।
  3. सुनिश्चित करें कि एक्सेस-कंट्रोल-अनुमति-उत्पत्ति एक और केवल एक डोमेन पर सेट है, जो अनुरोध मूल होना चाहिए। पहुँच-नियंत्रण-अनुमति-उत्पत्ति * पर सेट न करें।

यदि यह मदद नहीं करता है, तो इस लेख पर एक नज़र डालें। यह PHP पर है, लेकिन यह ठीक से वर्णन करता है कि कौन से हेडर को CORS के काम करने के लिए निर्धारित किया जाना चाहिए।

कोर आईई, फ़ायरफ़ॉक्स, क्रोम और सफारी में काम करता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.