I have a flask endpoint hosted on localhost:5000 that I am trying to send requests to from a React app hosted on localhost:3000. The endpoint looks like this:
#app.route('/createUserSession', methods=["POST", "OPTIONS", "GET"])
#cross_origin()
def createUserSession():
response = Response()
response.headers["Access-Control-Allow-Origin"] = "http://localhost:3000"
response.headers["Access-Control-Allow-Methods"] = ["GET", "POST", "OPTIONS"]
response.headers["Access-Control-Allow-Credentials"] = "true"
return response
I call it from the frontend using axios as follows:
const api = axios.create({
withCredentials: false,
crossorigin: true
});
api.post('http://127.0.0.1:5000/createUserSession', queryString.stringify(params),
{headers: headers})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
I tried various permutations of the headers, and each time get the CORS error telling me either the origin is not allowed or the credentials header is set to false. Is there any solution beyond using a proxy? Thanks!
Try to use Flask-CORS (https://flask-cors.readthedocs.io/en/latest/). Initialize the Flask-CORS where you have initialized the Flask application. The simple use case as stated in the Flask-CORS official documentation in the context of your code is:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app, resources={r"/createUserSession": {"origins": "*"}})
#app.route("/createUserSession")
def createUserSession():
return "user session response"
It's always better to have prefixes in API endpoints so that similar types of endpoints can be grouped together. For instance, you can change your endpoint to #app.route("/api/createUserSession")
After using this your CORS instance would be cors = CORS(app, resources={r"/api/*": {"origins": "*"}}), making it easier to cover other API endpoints with prefix /api in the same instance of CORS
Related
I have a FlaskAPI back-end and a Vue front-end and I am trying to send responses between the two. I am having an issue with the implementation of FlaskCors. This module should handle 'OPTIONS' as well from what I can tell, however I am having issues still. Any help would be appreciated. The documentation does not say to utilize the '#cross-origin' decorator if I choose to allow everything.
Javascript error:
Access to XMLHttpRequest at 'http://localhost:5000/login' from origin
'http://localhost:3000' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Flask Runner
#! /usr/bin/python3.6
from caffeine import create_app
import os
app = create_app()
# app.secret_key = os.environ.get("SECRET_KEY")
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=5000)
init.py
import os
from pathlib import Path
from flask_api import FlaskAPI
from flask_cors import CORS
from caffeine.config import Config
def create_app():
"""Instantiates and initialize the Flask application"""
app = FlaskAPI(__name__)
app.config.from_object(Config)
CORS(app)
from caffeine.routes.bp_auth import auth
app.register_blueprint(auth)
return app
Flask Config:
class Config:
"""Base configuration."""
API_VERSION = "1.0.0"
SECRET_KEY = os.environ.get("SECRET_KEY")
CORS_HEADERS = "Access-Control-Allow-Origin"
Flask Auth Blueprint:
#auth.route("/login", methods=["GET", "POST", "OPTIONS"])
def login():
"""
present the 'login-page' for entering LDAP credentials to be validated and added to the database
if user is already authenticated, they will be routed to the home route (routes.py)
:return: user login-in UI view
"""
if request.method == "POST":
user_sso = request.data["sso"].strip()
access_token = encode_access_token(user_sso)
response = jsonify(
status="success",
message="successfully logged in",
access_token=access_token,
token_type="bearer",
expires_in=get_token_expire_time(),
)
response.status_code = HTTPStatus.CREATED
response.headers["Cache-Control"] = "no-store"
response.headers["Pragma"] = "no-cache"
return response
i've had a similar problem with react, this is how i could solve it on my app:
class config:
CORS_ALLOW_CREDENTIALS = True
init.py
...
from flask_cors import CORS
cors = CORS()
def create_app():
...
cors.init_app(app=app, supports_credentials=True)
...
I'm trying to allow Same Origin request to my Flask app:
this is in my __init__.py file:
# ... other imports ...
from flask_cors import CORS
cors = CORS()
def create_app(script_info=None):
app = Flask(__name__)
app_settings = os.getenv('APP_SETTINGS')
app.config.from_object(app_settings)
from project.api.flakes import flakes_blueprint
app.register_blueprint(flakes_blueprint)
cors.init_app(flakes_blueprint, resources={r"/flakes": {"origins": "*"}})
return app
According to docs this should be sufficient to get it working but I get:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5001/flakes. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
How can I get it working ? I would've thought {"origins": "*"} covers everything.
I've not seen an example like you have provided using cors_init_app(), so cannot comment on why it doesn't work.
However, here is an example of I've used previously that works:
app = Flask(__name__)
CORS(app, resources={r'/*': {'origins': '*'}})
app.config['CORS_HEADERS'] = 'Content-Type'
app.register_blueprint(my_blueprint_module.bp)
I am calling a Flask API from React (both running on localhost) and I am running into CORS problems.
When the request is made, the browser (Chrome) gives the following error
Access to XMLHttpRequest at 'http://localhost:5000/sas' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
Setup
The Flask setup is the following
from flask_cors import CORS
from flask import Flask, request, Response
from flask_restful import Api, Resource
import json
class SAS(Resource):
def get(self):
content = request.json
js = json.dumps(
{
"Response": "Some response"
}
)
resp = Response(js, status=200, mimetype='application/json')
return resp
app = Flask(__name__)
cors = CORS(app)
api = Api(app)
api.add_resource(SAS, '/sas/')
The call using axios in React is the following
buttonPressed = async event => {
event.preventDefault();
const response = await axios.get(`http://localhost:5000/sas`, {
data: {
user: "user",
file_name: "user",
directory_name: "user"
}
});
};
NOTE: Running the request from Postman works and shows the header Access-Control-Allow-Origin = *
Any idea on how to solve the problem?
Also, if I was to run the React frontend and API as a dockerized application, I should not see this problem anymore correct? In this case I would also consider circumnavigating the problem while I am developing
Please try using the cross_origin decorator like in this minimal example:
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app, support_credentials=True)
#app.route('/sas', 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": "Nice Get Request"})
if __name__=="__main__":
app.run(host='0.0.0.0', port=5000)
If this works then we'll move to implement the same decorator in your code.
In my frontend app I'm trying to access a file I'm serving in a static folder but I'm getting an issue with CORS. The issue I'm seeing is
Access to XMLHttpRequest at 'http://127.0.0.1:5000/static_folder/apple.xml' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
My backend Flask app has the following set
app = Flask(__name__, static_url_path='/static_folder', static_folder="static_folder")
It seems that I need to add the 'Access-Control-Allow-Origin' header to my responses when returning the files. Does Flask have a global way to set this?
I've tried using flask_cors but haven't been successful with
from flask_cors import CORS, cross_origin
app = Flask(__name__, static_url_path='/static_folder', static_folder="static_folder")
CORS(app)
I was able to get something similar working with the SimpleHTTPRequestHandler by setting the CORS headers as
def end_headers (self):
self.send_header('Access-Control-Allow-Origin', '*')
SimpleHTTPRequestHandler.end_headers(self)
But I'd like to use flask to accomplish this rather than starting a simple http server.
after cors(app) add these lines:
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Headers', 'Content-Type, Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE, OPTIONS')
return response
Also, if using the flask-cors package, you should be able to blanket your static requests:
from flask import Flask
from flask_cors import CORS
# Initialize
app = Flask(__name__)
cors = CORS(app, resources={r"/static/*": {"origins": "*"}})
Good luck!
I want to allow only localhost as access-control-allow-origin in my Flask app. I tried searching for this issue at other places with no solution. My code is very simple and straightforward as follows :
from flask import Flask
from routes.routes import *
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "http://localhost:3000"}})
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/drax')
app.add_url_rule('/template/<actionId>/<actionName>', None, templateActions, methods=['GET'])
The above should ONLY allow any request from localhost:3000 and not from anywhere else, like localhost:8080. But even when I make the request from port 8080 (another web app), it allows the request.
Looks like you need to specify a valid http origin in your request as under:
CORS(
app,
supports_credentials=True,
resources={
r"/*": {
"origins": [
"http://localhost:3000",
""http://localhost"
"http://127.0.0.1:3000",
"http://127.0.0.1,
]
}
},
)
I do not think http://local is a valid origin