Javascript - No 'Access-Control-Allow-Origin' header is present on the requested resource

JavascriptPythonAjaxFlaskCors

Javascript Problem Overview


I need to send data through XmlHttpRequest from JavaScript to Python server. Because I'm using localhost, I need to use CORS. I'm using the Flask framework and its module flask_cors.

As JavaScript I have this:

    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);

and Python code:

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

But when I execute it I get this message:

> XMLHttpRequest cannot load localhost:5000/signin. No > 'Access-Control-Allow-Origin' header is present on the requested > resource. Origin 'null' is therefore not allowed access.

How should I fix it? I know that I need to use some "Access-Control-Allow-Origin" header but I don't know how to implement it in this code. By the way I need to use pure JavaScript.

Javascript Solutions


Solution 1 - Javascript

I have used the flask-cors extension.

Install using pip install flask-cors

Then it's simply

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

This will allow all domains

Solution 2 - Javascript

Old question, but for future googlers with this problem, I solved it (and a few other downstream issues having to do with CORS) for my flask-restful app by adding the following to my app.py file:

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 __name__ == '__main__':
    app.run()

Solution 3 - Javascript

I got Javascript working with Flask by using this decorator, and adding "OPTIONS" to my list of acceptable methods. The decorator should be used beneath your route decorator, like this:

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

Edit: Link appears to be broken. Here's the decorator I used.

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

Solution 4 - Javascript

When using 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 __name__ == '__main__':
    app.run()

When running on python3 or ahead, install flask-cors using the command pip install flask-cors The add the following:

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

Solution 5 - Javascript

There's actually a brilliant snippet on the Flask site to modify the Access-Control-Allow-Origin header server-side. http://flask.pocoo.org/snippets/56/

You have the easy way out from there, which is to allow every * domain to access your URL, or specifying your selection of URLs inside the header.

From the MDN's article on CORS:

> In this case, the server responds with a Access-Control-Allow-Origin: * which means that the > resource can be accessed by any domain in a cross-site manner. If the resource owners at > http://bar.other wished to restrict access to the resource to be only from > http://foo.example, they would send back: > Access-Control-Allow-Origin: http://foo.example.

Solution 6 - Javascript

I have used the solution from Zachary. Works well.

For those who are wondering where to place the new decorator:

Just copy the code from the link that Zachary provided and place it in a .py file

Place it in the folder where your python modules are present(varies based on what system you use and whether or not you are using a virtual environment).

In your flask app, import the method crossdomain from the newly created python module and use it.

Solution 7 - Javascript

The Access-Control-Allow-Origin must be sent by the server, not by you. When you make a call to another domain, the browser checks whether this header is returned by the server. If it isn't, the call fails. I don't know Python, so I don't know how to make your server send this header, or even if you can modify the server at all.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJaroslav KlimĨíkView Question on Stackoverflow
Solution 1 - JavascriptcampervancoderView Answer on Stackoverflow
Solution 2 - JavascriptLuc GendrotView Answer on Stackoverflow
Solution 3 - JavascriptZachary JacobiView Answer on Stackoverflow
Solution 4 - JavascriptAlok PatraView Answer on Stackoverflow
Solution 5 - JavascriptboxmeinView Answer on Stackoverflow
Solution 6 - JavascriptVikasView Answer on Stackoverflow
Solution 7 - JavascriptOscar PazView Answer on Stackoverflow