python ajax angularjs flask flask-restful

python - Flask Problema RESTful entre dominios con métodos Angular: PUT, OPTIONS



flask cors (7)

¿Qué tal esta solución alternativa?

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

Lo tomé de this tutorial. Funciona muy bien de hecho, creo que este es el mejor enfoque que he visto hasta ahora.

Volver {''Access-Control-Allow-Origin'': ''*''} en cada punto final no parece ser eficiente ya que debe agregarlo en cada punto final. un poco molesto ..., al menos para mí.

Intenté @cors.crossdomain(origin=''*'') pero parece que solo funciona con la solicitud GET .

Desarrollé una pequeña API REST de solo escritura con Flask Restful que acepta solicitudes PUT de un puñado de clientes que pueden tener direcciones IP cambiantes. Mis clientes están incrustados clientes de Chromium ejecutando un front-end AngularJS; se autentican con mi API con una simple llave mágica, es suficiente para mi escala muy limitada.

Estoy probando la implementación de mi API ahora y veo que los clientes angulares están intentando enviar un método OPTIONS http a mi servicio Flask. Mientras tanto, mi API responde con un 404 (ya que todavía no escribí un manejador OPTIONS, solo un manejador PUT). Parece que al enviar solicitudes de dominio cruzado que no son POST o GET, Angular enviará un método de OPCIONES previas al vuelo en el servidor para asegurarse de que se acepte la solicitud entre dominios antes de enviar la solicitud real. ¿Está bien?

De todos modos, ¿cómo permito todas las solicitudes de PUT entre dominios a Flask Restful API? He usado decoradores cross-domaion con una instancia Flask (no reposada) anteriormente, pero ¿necesito escribir un controlador OPTIONS también en mi API?


Con el módulo Flask-CORS , puede hacer solicitudes entre dominios sin cambiar su código .

from flask.ext.cors import CORS app = Flask(__name__) cors = CORS(app, resources={r"/api/*": {"origins": "*"}})

Actualizar

Como sugirió Eric , el módulo flask.ext.cors ahora está en desuso, debería usar el siguiente código:

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


Me gusta usar una decoración para resolver.

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

Y luego, usa la decoración en tu apacible 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


Puede usar el enganche after_request:

@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

Consulte este tutorial para obtener más información: http://tutsbucket.com/tutorials/building-a-blog-using-flask-and-angularjs-part-1/


Resolví el problema reescribiendo mi servidor Flask para responder con un encabezado Access-Control-Allow-Origin en mi respuesta PUT. Además, creé un controlador OPTIONS en mi aplicación Flask para responder al método de opciones siguiendo lo que leí en el RFC de http.

El retorno en el método PUT se ve así:

return restful.request.form, 201, {''Access-Control-Allow-Origin'': ''*''}

El controlador de métodos de mi OPCIONES se ve así:

def options (self): return {''Allow'' : ''PUT'' }, 200, / { ''Access-Control-Allow-Origin'': ''*'', / ''Access-Control-Allow-Methods'' : ''PUT,GET'' }

@tbicr tiene razón: Flask SÍ responde automáticamente el método de OPCIONES. Sin embargo, en mi caso no transmitía el encabezado Access-Control-Allow-Origin con esa respuesta, por lo que mi navegador recibía una respuesta de la API que parecía implicar que no se permitían las solicitudes entre dominios. Sobrecargué la solicitud de opciones en mi caso y agregué el encabezado ACAO, y el navegador pareció estar satisfecho con eso, y seguí OPCIONES con un PUT que también funcionó.


Solo una actualización de este comentario. Flask CORS es el camino a seguir, pero el matraz.ext.cors está en desuso.

uso: from flask_cors import CORS


Tiene razón, el método OPTIONS se llama cada vez antes de la solicitud real en el navegador. OPTIONS respuesta OPTIONS ha permitido métodos y encabezados. Flask procesa automáticamente las solicitudes OPTIONS .

Para obtener acceso para solicitud de dominio cruzado, la API debe tener el encabezado Access-Control-Allow-Origin . Puede contener dominios específicos, pero si desea permitir solicitudes desde cualquier dominio, puede configurarlo como Access-Control-Allow-Origin: * .

Para configurar CORS para el flask , puede ver un código de extensión o intentar usar esta extensión: https://github.com/wcdolphin/flask-cors/blob/master/flask_cors.py .

Para configurar CORS para flask-restful mira estas solicitudes de extracción: https://github.com/twilio/flask-restful/pull/122 y https://github.com/twilio/flask-restful/pull/131 . Pero parece que flask-restful aún no lo admite por defecto.