web-dev-qa-db-fra.com

Javascript - Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée

J'ai besoin d'envoyer des données via XmlHttpRequest depuis JavaScript vers Python. Comme j'utilise localhost, je dois utiliser CORS . J'utilise le framework Flask et son module flask_cors.

En JavaScript, j'ai ceci:

    var xmlhttp;
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
    }
    else {// code for IE6, IE5
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.open("POST", "http://localhost:5000/signin", true);
    var params = "email=" + email + "&password=" + password;


    xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
        if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            alert(xmlhttp.responseText);
        }
    }
    xmlhttp.send(params);

et Python code:

@app.route('/signin', methods=['POST'])
@cross_Origin()
def sign_in():
    email = cgi.escape(request.values["email"])
    password = cgi.escape(request.values["password"])

Mais quand je l'exécute, je reçois ce message:

XMLHttpRequest ne peut pas charger localhost: 5000/signin. Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée. Origin 'null' n'est donc pas autorisé à accéder.

Comment dois-je le réparer? Je sais que j'ai besoin d'utiliser un en-tête "Access-Control-Allow-Origin" mais je ne sais pas comment l'implémenter dans ce code. En passant, je dois utiliser du JavaScript pur.

45

J’ai utilisé Javascript avec Flask en utilisant ceci décorateur , et en ajoutant "OPTIONS" à ma liste de méthodes acceptables. Le décorateur doit être utilisé sous votre décorateur de route, comme cette:

@app.route('/login', methods=['POST', 'OPTIONS'])
@crossdomain(Origin='*')
def login()
    ...

Edit: Le lien semble être rompu. Voici le décorateur que j'ai utilisé.

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

def crossdomain(Origin=None, methods=None, headers=None, max_age=21600,
                attach_to_all=True, automatic_options=True):
    """Decorator function that allows crossdomain requests.
      Courtesy of
      https://blog.skyred.fi/articles/better-crossdomain-snippet-for-flask.html
    """
    if methods is not None:
        methods = ', '.join(sorted(x.upper() for x in methods))
    # use str instead of basestring if using Python 3.x
    if headers is not None and not isinstance(headers, basestring):
        headers = ', '.join(x.upper() for x in headers)
    # use str instead of basestring if using Python 3.x
    if not isinstance(Origin, basestring):
        Origin = ', '.join(Origin)
    if isinstance(max_age, timedelta):
        max_age = max_age.total_seconds()

    def get_methods():
        """ Determines which methods are allowed
        """
        if methods is not None:
            return methods

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

    def decorator(f):
        """The decorator function
        """
        def wrapped_function(*args, **kwargs):
            """Caries out the actual cross domain code
            """
            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)
            h['Access-Control-Allow-Credentials'] = 'true'
            h['Access-Control-Allow-Headers'] = \
                "Origin, X-Requested-With, Content-Type, Accept, Authorization"
            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
32
Zachary Jacobi

J'ai utilisé l'extension flask-cors.

Installez en utilisant pip install flask-cors

Alors c'est simplement

from flask_cors import CORS
app = Flask(__name__)
CORS(app)

Cela permettra à tous les domaines

70
campervancoder

Vieille question, mais pour les futurs googleurs avec ce problème, je l'ai résolu (et quelques autres problèmes en aval concernant CORS) pour mon application reposante en ajoutant ce qui suit à mon fichier app.py:

app = Flask(__name__)
api = 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,OPTIONS')
  return response


if __== '__main__':
    app.run()
43
Luc Gendrot

Lorsque vous utilisez python 2.7

app = Flask(__name__)
api = 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,OPTIONS')
  return response


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

Si vous utilisez python3 ou une version ultérieure, installez flask-cors en utilisant la commande pip install flask-cors Le ajouter ce qui suit:

from flask_cors import CORS
app = Flask(__name__)
CORS(app)
18
Alok Patra

Il y a en fait un extrait brillant sur le site Flask pour modifier le Access-Control-Allow-Origin en-tête côté serveur. http://flask.pocoo.org/snippets/56/

Vous avez le moyen facile de sortir de là, qui consiste à permettre à chaque * domaine pour accéder à votre URL ou spécifiez votre sélection d’URL dans l’en-tête.

Du article de MDN sur CORS :

Dans ce cas, le serveur répond par un Access-Control-Allow-Origin: * ce qui signifie que n'importe quel domaine peut accéder à la ressource de manière intersite. Si les propriétaires de ressources de http: //bar.other souhaitaient restreindre l'accès à la ressource uniquement à partir de http: //foo.example , ils renverraient: Access-Control-Allow-Origin: http://foo.example.

6
boxmein

J'ai utilisé la solution de Zachary. Fonctionne bien.

Pour ceux qui se demandent où placer le nouveau décorateur:

Il suffit de copier le code du lien fourni par Zachary et de le placer dans un .py fichier

Placez-le dans le dossier où se trouvent vos python (varie en fonction du système que vous utilisez et du fait que vous utilisiez ou non un environnement virtuel).

Dans votre flask), importez la méthode crossdomain à partir du module python) nouvellement créé et utilisez-la.

2
Vikas

Le Access-Control-Allow-Origin doit être envoyé par le serveur, pas par vous. Lorsque vous appelez un autre domaine, le navigateur vérifie si cet en-tête est renvoyé par le serveur. Si ce n'est pas le cas, l'appel échoue. Je ne connais pas Python, je ne sais donc pas comment faire en sorte que votre serveur envoie cet en-tête, ni même si vous pouvez modifier le serveur.

0
Oscar Paz