Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
125
rated 0 times [  126] [ 1]  / answers: 1 / hits: 97161  / 10 Years ago, tue, march 4, 2014, 12:00:00

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.


More From » python

 Answers
60

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

[#72159] Monday, March 3, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
rylee

Total Points: 658
Total Questions: 114
Total Answers: 116

Location: Christmas Island
Member since Mon, Oct 19, 2020
4 Years ago
;