Dla następującego ajax
żądania posta Flask
( jak mogę użyć danych wysłanych z ajax w kolbie? ):
$.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 );
}
});
Wyskakuje mi Cross Origin Resource Sharing (CORS)
błąd:
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.
Próbowałem rozwiązać to na dwa następujące sposoby, ale żaden z nich nie działa.
- Korzystanie z Flask-CORS
Jest to Flask
rozszerzenie obsługi, CORS
które powinno umożliwić obsługę AJAX między źródłami.
- http://flask-cors.readthedocs.org/en/latest/
- Jak włączyć CORS w kolbie i heroku
- Owijka Flask-Cors nie działa po zastosowaniu opakowania jwt auth.
- Javascript - Żądany zasób nie zawiera nagłówka „Access-Control-Allow-Origin”
Mój pythonServer.py korzystający z tego rozwiązania:
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()
- Korzystanie z określonego dekoratora kolb
To jest oficjalny fragment kodu Flask definiujący dekorator, który powinien zezwalać CORS
na funkcje, które ozdabia.
- http://flask.pocoo.org/snippets/56/
- Python Flask HTTP POST między witrynami - nie działa dla określonych dozwolonych źródeł
- http://chopapp.com/#351l7gc3
Mój pythonServer.py korzystający z tego rozwiązania:
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()
Czy możesz wskazać, dlaczego tak jest?
Odpowiedzi:
Działał jak mistrz, po niewielkiej modyfikacji kodu
# 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()
Zastąpiłem * przez localhost. Ponieważ czytałem w wielu blogach i postach, powinieneś zezwolić na dostęp dla określonej domeny
źródło
Możesz uzyskać wyniki za pomocą prostego:
@app.route('your route', methods=['GET']) def yourMethod(params): response = flask.jsonify({'some': 'data'}) response.headers.add('Access-Control-Allow-Origin', '*') return response
źródło
yourMethod
to:return render_template('template.html',some_var = response)
Cóż, miałem ten sam problem. Dla nowych użytkowników, którzy mogą wylądować na tej stronie. Wystarczy postępować zgodnie z ich oficjalną dokumentacją.
Zainstalować korki do kolb
pip install -U flask-cors
następnie po zainicjowaniu aplikacji zainicjuj
flask-cors
z domyślnymi argumentami:from flask import Flask from flask_cors import CORS app = Flask(__name__) CORS(app) @app.route("/") def helloWorld(): return "Hello, cross-origin-world!"
źródło
Access-Control-Max-Age
zaflask_cors
?Równie dobrze może to być odpowiedź. Miałem dzisiaj ten sam problem i nie był to problem bardziej niż oczekiwano. Po dodaniu funkcji CORS należy zrestartować serwer Flask (
ctrl + c
->python manage.py runserver
lub jakąkolwiek metodę, której używasz)), aby zmiana odniosła skutek, nawet jeśli kod jest poprawny. W przeciwnym razie CORS nie będzie działać w aktywnym wystąpieniu.Oto jak to wygląda u mnie i działa (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" })
W mojej aplikacji console.log w React:
Sending request: GET /stuff With parameters: null bundle.js:17316 Received data from Api: {"stuff": "Here be stuff"}
źródło
Zwróć uwagę, że ustawienie
Access-Control-Allow-Origin
nagłówka w obiekcie odpowiedzi Flask jest w wielu przypadkach poprawne (na przykład w tym), ale nie ma wpływu na obsługę zasobów statycznych (przynajmniej w konfiguracji produkcyjnej). Dzieje się tak, ponieważ statyczne zasoby są obsługiwane bezpośrednio przez przedni serwer sieciowy (zwykle Nginx lub Apache). Więc w takim przypadku musisz ustawić nagłówek odpowiedzi na poziomie serwera WWW, a nie w Flasku.Aby uzyskać więcej informacji, zobacz ten artykuł, który napisałem jakiś czas temu, wyjaśniając, jak ustawić nagłówki (w moim przypadku próbowałem udostępniać zasoby Font Awesome w wielu domenach).
Ponadto, jak powiedział @Satu, może być konieczne zezwolenie na dostęp tylko dla określonej domeny, w przypadku żądań JS AJAX. Jeśli chodzi o żądanie zasobów statycznych (takich jak pliki czcionek), myślę, że reguły są mniej surowe, a zezwalanie na dostęp dla dowolnej domeny jest bardziej akceptowane.
źródło
Użyłem dekoratora podanego przez Armina Ronachera z niewielkimi modyfikacjami (ze względu na różne nagłówki, o które prosi klient) i to zadziałało. (gdzie używam angular jako requester żądający typu application / json).
Kod jest nieznacznie zmodyfikowany w poniższych miejscach,
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 wyśle typ aplikacji / json, w przeciwnym razie będzie to tekst / html. nagłówki są dodawane jako żądanie klienta w moim przypadku dla tych nagłówków
const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json', 'Access-Control-Allow-Origin':'*' }) }; return this.http.post<any>(url, item,httpOptions)
źródło
Uwaga: Umieszczenie cross_origin powinno być poprawne, a zależności są zainstalowane. Po stronie klienta upewnij się, że określono rodzaj zużywanego przez serwer danych. Na przykład application / json lub text / html
U mnie poniższy kod zrobił magię
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)
źródło
cross_origin
?Mogę się spóźnić z tym pytaniem, ale poniższe kroki rozwiązały problem
from flask import Flask from flask_cors import CORS app = Flask(__name__) CORS(app)
źródło
Dużo walczyłem z czymś podobnym. Spróbuj wykonać następujące czynności:
Jeśli to nie pomoże, zajrzyj do tego artykułu. Jest w PHP, ale opisuje dokładnie, które nagłówki muszą być ustawione na jakie wartości, aby CORS działał.
CORS, który działa w IE, Firefox, Chrome i Safari
źródło