Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask Access-Control-Allow-Origin for multiple URLs

Tags:

python

cors

flask

I have an API written in python/flask and I want to allow only a couple URLs to access this API. The JavaScript call is trivial jQuery, like:

    $.ajax({
     url: "http://myApi.com/api/doit",  
     dataType:'JSON',
     success:function(data){
       console.log("DEBUG: yeeeeaaaahhh!");
     },
     error:function(xhr){
       console.log("Error occured! status: " + xhr.status + ", text: " + xhr.statusText);
     }
  });

Most of the solutions mainly here are pretty disappointing always offering to set Access-Control-Allow-Origin : '*' or to start chrome disabling the check. Of course it works, but this is not the purpose. The spec on w3 says a semicolon separated list should work, but it doesn't. Also comma separated list failed. From flask itself there is http://flask.pocoo.org/snippets/56/ but it does not work with multiple URLs. In the comments there is a suggestion: h.extend([("Access-Control-Allow-Origin", orig) for orig in origin]) but it still does not work.

The only solution I have is to check in code the origin and in case it is in my white list to put in the header Access-Control-Allow-Origin : '*'. This is a workaround but I don't like it that much. Can you suggest a more elegant solution?

like image 406
oggo Avatar asked Mar 08 '17 20:03

oggo


2 Answers

This is typical scenario when working locally with multiple instances of the same frontend project accessing together to a local Flask server, and when the wildcard "*" is not allowed because you are allowing credentials (i.e. using a JWT authentication).

My approach - in development - is to use the after_request decorator and Flask's request context.

Create a domain whitelist:

white = ['http://localhost:8080','http://localhost:9000']

Now use the after_request decorator to intercept all incoming requests, check if the referrer is in your whitelist and, if it is, inject the response.headers to allow access to the origin. For example:

from flask import request

@app.after_request
def add_cors_headers(response):
    r = request.referrer[:-1]
    if r in white:
        response.headers.add('Access-Control-Allow-Origin', r)
        response.headers.add('Access-Control-Allow-Credentials', 'true')
        response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
        response.headers.add('Access-Control-Allow-Headers', 'Cache-Control')
        response.headers.add('Access-Control-Allow-Headers', 'X-Requested-With')
        response.headers.add('Access-Control-Allow-Headers', 'Authorization')
        response.headers.add('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE')
    return response
like image 108
TMichel Avatar answered Oct 17 '22 08:10

TMichel


Simple example,try it!
I hope it will help you. You need to edit white_origin for 'Access-Control-Allow-Origin'.

app_name.py (Python file of Flask )

from flask import request

@app.after_request
def after_request(response):
    white_origin= ['http://www.dom.com:8000','http://localhost']
    if request.headers['Origin'] in white_origin:
        response.headers['Access-Control-Allow-Origin'] = request.headers['Origin'] 
        response.headers['Access-Control-Allow-Methods'] = 'PUT,GET,POST,DELETE'
        response.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization'
    return response
like image 25
Dondon Jie Avatar answered Oct 17 '22 09:10

Dondon Jie