Max Baldwin
Max Baldwin

Reputation: 3452

Python Flask Cors Issue

I am kind of new to Python, but I have had the same issue working with Node apps. I am making a pretty standard jQuery AJAX request to my local Python sever:

init: function(callback) {
            var token = _config.get_token();

            $.ajax({
                    url: 'http://localhost:5000/api/ia/v1/user_likes',
                    type: 'POST',
                    contentType: 'application/json',
                    datatype: 'json',
                    data: token
                })
                .done(function(data) {
                    callback(data);
                })
                .fail(function(err) {
                    callback(err);
                });

            callback(token);
        }

I can confirm that the variable token is confirming like this:

Object {access_token: "791415154.2c0a5f7.4d707361de394512a29682f9cb2d2846", campaign_id: "102"}

But I am getting this error from my javascript console:

XMLHttpRequest cannot load http://localhost:5000/api/ia/v1/user_likes. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://s3.amazonaws.com' is therefore not allowed access. The response had HTTP status code 500.

I have found that when I am building Node apps that this is a cors error. The page that I am running the jQuery AJAX request from is http. Here are the parts of my Python code that I believe I am configuring incorrectly:

from flask import Flask, request, redirect
from flask.ext.cors import CORS, cross_origin

app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'application/json'

And the route:

@app.route("/api/ia/v1/user_likes", methods=['POST', 'OPTIONS'])
def user_likes():
    validate = validate_request(request.data)

    return 'something'

My Python error is also returning an error because the request is never making it to this line of code:

def validate_request(object_from_user):
    load_object = json.loads(object_from_user)

I can fix that later. Anyway, does anyone have any suggestions for Cors configurations for Python?

Upvotes: 34

Views: 154828

Answers (13)

nfon andrew
nfon andrew

Reputation: 117

I basically followed @david and it worked well for me, here is how i returned my response

first i installed flask-cors

from flask_cors import CORS, cross_origin


app = Flask(__name__)
CORS(app, support_credentials=True)

used it on my endpoint

@cross_origin() # added this to my endpoint
@app.route('/api/verify-authenticity', methods=['POST'])
def verify_image(): 

then returned my response with the following headers

 return Response(
                response,
                headers={
                    "Content-Type": "application/json",
                    "Access-Control-Allow-Origin": '*',
                    "Access-Control-Allow-Methods": 'PUT, GET, POST, DELETE, OPTIONS',
                    "Access-Control-Allow-Headers": 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
                },
                content_type='application/json'
            )

Upvotes: 2

pxeba
pxeba

Reputation: 1766

Please note that if your application returns a 500 error your browser may understand it as a cors error as flask cors only adds headers on return.

So, if the other options don't work you can put your flask in debug mode to validate if it's not just an internal server error.

.flaskenv

FLASK_ENV=development

Upvotes: 1

Pol Zeimet
Pol Zeimet

Reputation: 61

I tried all of the above solutions and they kept failing for me. I am sure, most solutions would have worked, but there was one very obvious mistake I made in my client application. Maybe this saves some of you a bit of debugging time. I my request, I called my REST-service via

'localhost:<port>/<myApi>'

The fix for me was as simple as calling the service as http... :

'http://localhost:<port>/<myApi>'

A silly mistake.

Upvotes: 5

naik899
naik899

Reputation: 116

I have installed flask using the following command and using the declaration like this:

pips3.6 install --user flask-cors

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

Upvotes: -2

Dila Gurung
Dila Gurung

Reputation: 1764

On client side you only need to ensure that kind of data your server is dealing with. For example form data or json.

Note: The placement of cross_origin should be right.

For me the code written below did magic

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)

Upvotes: 1

Dorian
Dorian

Reputation: 153

Based on GyuHyeon Choi's response, but with added return response and an extra Access-Control-Expose-Headers worked for me.

@app.after_request
def add_headers(response):
    response.headers.add('Content-Type', 'application/json')
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS')
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
    response.headers.add('Access-Control-Expose-Headers', 'Content-Type,Content-Length,Authorization,X-Pagination')
    return response

Upvotes: 0

Manivannan Murugavel
Manivannan Murugavel

Reputation: 1578

Please use @cross_origin(origin='*') in your python file

from flask import Flask, jsonify
from flask_cors import CORS, cross_origin

app = Flask(__name__)

@app.route("/login", methods = ['GET'])
@cross_origin(origin='*')
def login():
  return jsonify({'success': 'ok'})

if __name__ == "__main__":
  app.run(host='0.0.0.0', port=8000, debug=True)

Upvotes: 8

Alan Dong
Alan Dong

Reputation: 4095

After I tried others suggestions and answers. Here's what I use, which works.

Steps:

  1. pip install flask flask-cors

  2. Copy and paste this in app.py file

Code

from flask import Flask, jsonify
from flask_cors import CORS, cross_origin

app = Flask(__name__)
CORS(app, support_credentials=True)

@app.route("/login")
@cross_origin(supports_credentials=True)
def login():
  return jsonify({'success': 'ok'})

if __name__ == "__main__":
  app.run(host='0.0.0.0', port=8000, debug=True)
  1. python app.py

Note: be sure in your client's ajax configuration has the following:

$.ajaxSetup({
    type: "POST",
    data: {},
    dataType: 'json',
    xhrFields: {
       withCredentials: true
    },
    crossDomain: true,
    contentType: 'application/json; charset=utf-8'
});

If one wonders, support_credentials=True just means it sends cookies along the payload back and forth.

Upvotes: 41

user7176771
user7176771

Reputation: 239

Flask has the flask-cors module. Following is the code snippet as well as the procedure.

  1. pip install -U flask-cors

  2. Add this lines in your flask application:

    from flask import Flask
    from flask_cors import CORS, cross_origin
    
    app = Flask(__name__)
    CORS(app)
    
    @app.route("/")
    def helloWorld():
        return "Hello world"
    

See more by clicking on this link

Upvotes: 22

ghchoi
ghchoi

Reputation: 5156

Try this:

@app.after_request
def add_headers(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')

I've tried @cross_origin tutorial on the Flask website,however, it did not work for me.

But it seems like you can add headers to your response later.

Here is my remaining code that I think it may be useful.

from flask import Flask, request
from sklearn.externals import joblib

app = Flask(__name__)

Upvotes: 1

Lyfing
Lyfing

Reputation: 1916

Here is how to get your hand dirty by handling the CORS detail all by yourself:

handle_result = {'result': True, 'msg': 'success'}

try:
    # origin, where does this request come from, like www.amazon.com
    origin = flask.request.environ['HTTP_ORIGIN']
except KeyError:
    origin = None

# only accept CORS request from amazon.com
if origin and origin.find('.amazon.com') > -1:
    resp = flask.make_response(str(handle_result))
    resp.headers['Content-Type'] = 'application/json'

    h = resp.headers
    # prepare headers for CORS authentication
    h['Access-Control-Allow-Origin'] = origin
    h['Access-Control-Allow-Methods'] = 'GET'
    h['Access-Control-Allow-Headers'] = 'X-Requested-With'

    resp.headers = h
    return resp

return flask.abort(403)

Upvotes: 7

Shasti
Shasti

Reputation: 91

The below solution worked for me. I included a method that will add the headers necessary for you and then raise the HTTP response. Ex:

def some_method(response_data, status_code):
    response_data = //here you can manipulate the data, JSONify, convert arrays into objects or vice versa
    headers = {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin": '*',
        "Access-Control-Allow-Methods": 'PUT, GET, POST, DELETE, OPTIONS',
        "Access-Control-Allow-Headers": 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
        }
    //THEN RAISE HTTPResponse
    raise HTTPResponse(status, headers, body)

Note: The above method is not python compiling so you may have to edit it.

Upvotes: 1

Derek
Derek

Reputation: 60

use the cors decorator after the route decorator.

here's a snippet from the documentation...

@app.route("/")
@cross_origin() # allow all origins all methods.
def helloWorld():
  return "Hello, cross-origin-world!"

now, it appears you are using json, if that's the case, you should likely just read the documentation as it specifically mentions this use case, and what cors_headers to set... it's below the fold, but this documentation is well written and easy to understand.

http://flask-cors.readthedocs.org/en/latest/#using-json-with-cors

Upvotes: 4

Related Questions