Flask API deployed with Heroku 'CORS blocked' error - reactjs

I'm having issues on my application that has been deployed to Heroku. When I was developing it on localhost, I didn't get this error, but once I deployed it, it spontaneously throws this error:
Access to fetch at
'https://frontend.herokuapp.com' from origin
'https://backend.herokuapp.com' has been blocked
by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource. If an opaque response serves your needs,
set the request's mode to 'no-cors' to fetch the resource with CORS
disabled.
Simplified version of my Flask server:
from flask import Flask, request, make_response, jsonify, url_for,
redirect, render_template
from flask_cors import CORS, cross_origin
import flask
import json
app = Flask(__name__)
CORS(app)
#app.route('/api/action', methods=['GET', 'POST'])
#cross_origin()
def prescription(response={}):
# POST request
if request.method == 'POST':
print('score POST request')
response = request.get_json()
data = json.loads(response.get('data'))
rating = a_super_cool_feature
return jsonify(rating), 200
# GET request
else:
print('GET request')
return getScore(response)
#app.route('/api/score', methods=['GET', 'POST'])
#cross_origin()
def scoreHandler(response={}):
# POST request
if request.method == 'POST':
print('Incoming..')
response = request.get_json()
parseResponse(response)
return str(getScore(response)), 200
# GET request
else:
return getScore(response)
#app.route('/test')
def test_page():
# look inside `templates` and serve `index.html`
return render_template('index.html')
if __name__ == "__main__":
app.debug=True
app.run()
My front-end is a React application. These two servers run on separate Heroku servers and I'm using the free version so I only get one dyno at a time (in case this could cause this error).
The interesting thing is this:
About half the time, when these POST requests are called on the deployed Heroku app, the error is thrown. Otherwise, it works no problem. Any ideas on fixing this?

You could use this snippet to enable cors app wide.
from flask import Flask
from flask_cors import CORS
app = Flask(__name__) CORS(app)

Okay now I actually fixed it. I bought the "Hobby" dyno type in Heroku and I never get the error now. I think it just has to do with the other server not being up and running when I make the request because I can only have one dyno running at a time with the free version. Thus it somehow timed out and gives that error.
With the Hobby dyno type my backend is always running so when I make a request it no longer times out and gives that error.

Really weird psuedo fix. Basically it was giving me this error about 40% of the time I made the POST request to the Flask backend, then I added
app.config['CORS_HEADERS'] = 'Content-Type'
Under the:
app = Flask(__name__)
CORS(app)
And this did not fix the issue completely. However; now this error is only thrown about 5% of the time when requests are made to the back-end. See other answer for actual fix.

Related

CORS Not Working - No Access-Control-Allow-Origin' header

thank you for taking a look at my question. I have been building my flask app to help deliver some calculatoins in python to my React front end. I am attempting to bridge the gap between the two different servers but am having trouble with CORS (from the looks of it along with many others new to flask with react)
I have tried to change around many things like adding #cross_origin, origins: '', and headers.add("Access-Control-Allow-Origin", "") but no success. All I need from flask is the result of my functions. Has anyone else run into an issue similar or know a way I can fix this?
Flask Code:
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*", "allow_headers": "*", "expose_headers": "*"}})`
#app.route('/')
#cross_origin()
def welcome():
response = jsonify({'reply': 'Hello Webminers'})
response.headers.add("Access-Control-Allow-Origin", "*")
return response
React Code:
console.log(axios.get('http://127.0.0.1:5000'))
Console:
Access to XMLHttpRequest at 'http://127.0.0.1:5000/' from origin 'http://localhost:3000' has been
blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested
resource.
Failed to load resource: net::ERR_FAILED
P.S not sure if this matters or not but I have also gotten the same response with 'localhost:5000 from origin localhost:3000'
Edit:
axios.get('http://127.0.0.1:5000', {headers: {"Access-Control-Allow-
Origin": "*"}}).then(response => {
console.log(response.data);
})
I added this in and got this new response from the console
Access to XMLHttpRequest at 'http://127.0.0.1:5000/' 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
I believe that I found the issue. I was looking around and trying a bunch of different things and even attempted to recreate the API in fastAPI to reach the same results.
However, I have just found this comment stating that they had an issue where React would be running but leaving the API behind thus causing errors for not being able to get the data from my API. https://stackoverflow.com/a/58786845/19683392
I am currently still looking for the solution and may open a new question but for now, I am getting this error:
TypeError: NetworkError when attempting to fetch resource.
More updates soon...
*** Edit ***
FOUND IT!
Bam fixed it with the concurrent library's help
"start": "concurrently \"react-scripts start\"
\"flask --app Backend/FlaskAPI.py run\"",
Is the config I used for anyone else who runs into the same issue
You don't need to manually set the header, the CORS package will handle that for you. Also in frontend you don't need to specify CORS header when calling the API
Can you try the following way?
app = Flask(__name__)
CORS(app)
#app.route('/')
#cross_origin()
def welcome():
response = jsonify({'reply': 'Hello Webminers'})
return response
Then access the api like this:
axios.get('http://127.0.0.1:5000').then(response => {
console.log(response.data);
})

Why React can't reach Flask endpoints in production?

I've got a React app with Flask on the backend in production and I found out
that none of my endpoints are reached from React.
I'm aware that when using client-side routing developer needs to use a catch-all function
similar to the below:
#app.errorhandler(404)
def error_handler(e):
return render_template('index.html')
I'm using Flask-CORS to handle cross origin requests:
within config.py:
class ProductionConfig:
CORS_HEADERS = 'Content-Type'
...
...
my blueprint:
CORS(auth_blueprint, resources={r'/*': {"origins": "https://example.com", "allow_headers": "*", "expose_headers": "*"}})
#auth_blueprint.route('/auth/login', methods=['POST'])
#cross_origin()
def login():
...
...
on the frondend I'm defining headers like this:
const headers = { "Access-Control-Allow-Origin": "*" };
const url = "https://example.com:5000/auth/login";
axios.post(url, data, headers).then(resp => { ... })
And I'm not getting any errors whatsoever. Server's logs are clean and the console only shows Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com:5000/auth/login. (Reason: CORS request did not succeed).
"Reason: CORS request did not succeed" means that the server didn't return anything.
The app renders fine however React (axios) can't reach my endpoints. Are there any gotchas I'm not aware of ? When request is sent I'm not even getting a status code in the network tab.
Thank you.
Screenshot of the network tab:
You need to change the connection protocol to http.

https associated to an insecure XMLHttpRequest endpoint

My website is hosted on a cloud run app : https://ap4-xxxxxxxx.a.run.app/.
This website is calling an API which is hosted here https://ap4-xxxxxxxx.a.run.app/api/undefined. But this request is blocked in my browser .
Error message :
Mixed Content: The page at 'https://ap4-xxxxxxxx.a.run.app/' was
loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint
'http://ap4-xxxxxxxx.a.run.app/api/undefined/'. This request has been
blocked; the content must be served over HTTPS.
The API https://ap4-xxxxxxxx.a.run.app/api/undefined is working perfectly on my browser or with postman. And the code requesting it explicitly mentionned https :
const request = https://ap4-xxxxxxxx.a.run.app/api/${variable};
axios.get(request)
.then(result => {
const PlaceList = result.data.map(
station => {
const isFavorite = PlaceId.includes(Place.number);
return { ...Place, isFavorite: isFavorite }
}
);
this.setState({
PlaceList: PlaceList,
isLoading: false
})
updateFavPlaceList(PlaceList);
})
I don't understand what's wrong here. Is my app making an http call instead of https ? I read here (Page loaded over HTTPS but requested an insecure XMLHttpRequest endpoint) that, some https are self signed. Is it the case of cloud run?
I've tried Cors, but it did not help.
Any observation or suggestion would be very much appreciated.
It seems you are indeed somewhere making an HTTP:// request in your frontend or make sure your app doesn't issue redirects to http://.
.app domains are in hardcoded HSTS list of your browser. If you type any .app domain, it will be requested as https:// .There's no way to access a .app domain over http:// in a modern browser, even with XHR.
So here is a quick fix. I forced my backend (flask) to generate https url.
Using the answer from here : Flask url_for generating http URL instead of https
class ReverseProxied(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
scheme = environ.get('HTTP_X_FORWARDED_PROTO')
environ['wsgi.url_scheme'] = 'https'
app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)
There might be a better way (maybe forcing the frontend to request https), so feel free to comment on this.

CORS request did not succeed - react

I make this API request , using axios in ReactJS
axios.post(`${API_URL}/valida_proximo`, {
id: images.map(image => image.id)
},
getAxiosConfig())
// this.setState({ images, loadingAtribuiImagens: false})
}
It works really well in Google Chrome, but on Firefox I receive an error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/valida_proximo. (Reason: CORS request did not succeed).[Learn More]
What can I do?
This is my API
#blueprint.route('', methods=['POST', ])
#jwt_required()
def index():
if request.json:
id_usuarioImagem = request.json.get('id')
imagens_selecionadas =
UsuarioImagem.query.filter(UsuarioImagem.id.in_(id_usuarioImagem)).all()
if imagens_selecionadas:
for imagem_selecionada in imagens_selecionadas:
imagem_selecionada.batido=True
db.session.commit()
return 'ok', 200
return 'error', 400
CORS errors are usually associated with cross domain requests and something not configured to accept a request on the recipient side of the request. The fact that chrome is working but firefox doesn't seems rather strange.
This was a method I used:
Open Firefox browser and load the page.
Perform the operation which is throwing Cross Origin Request Security (CORS) error.
Open firebug and copy the URL which is throwing Cross Origin Request Security (CORS) error.
Load the same URL in another tab in same Firefox browser.
Once you open the URL in another tab will ask you to add the certificate.
After adding the certificate will resolve Cross Origin Request Security (CORS) error and now you will not be getting this error.
I'm not too familiar with Axios, but it looks like you're making a post request from your React to your Flask backend. If the front-end and the backend are on different ports (like your Flask seems to be on PORT 5000), then you're making a CORS request.
With CORS, depending on what you're posting, you might need to include some Access-Control headers in your Flask response object. You can do this either manually, or just pip-installing and using the 'flask-cors' package. Import the package into your app factory and use it like so (see their docuementation for more info):
from flask_cors import CORS
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
CORS(app)
The request might also get 'preflighted' with an 'OPTIONS' request, also depending on the nature of your POST. More information would be helpful
This is a bug in firefox.
if you follow the link (MDN) in the error msg . you will find:
What went wrong?
The HTTP request which makes use of CORS failed because the HTTP connection failed at either the network or protocol level. The error is not directly related to CORS, but is a fundamental network error of some kind.
which i read as the connection failed and not a problem with CORS settings.
you will just have to ignore the error message until firefox gets it fixed.
The error has something to do with refreshing the page and long polling requests or service workers and polling requests.
If anyone sees this question again, I had this problem because I made a request to https://url instead of http://url

Enable CORS in a Backbone client with a Flask server

I want to do cross domain requests between my backbone app at 127.0.0.1 and and my Flask server at 127.0.0.1:5000. Before I switched to a Backbone I had an Ember.js app and I had the same problem. But I got it working by adding this in my Flask app:
#app.after_request
def after_request(data):
response = make_response(data)
response.headers['Content-Type'] = 'application/json'
response.headers['Access-Control-Allow-Origin'] = 'http://localhost'
return response
and configure the Ember RESTAdapter this way:
adapter: DS.RESTAdapter.create({
url : 'http://127.0.0.1:5000',
// In order to allow cross domain requests
ajax: function(url, type, hash) {
jQuery.ajax(url)
}
})
});
But this does not work with my Backbone application.
XMLHttpRequest cannot load http://127.0.0.1:5000/files.
Request header field Content-Type is not allowed by Access-Control-Allow-Headers.
I guess I've to change some settings on the client side. But I don't know what.
What do I've to do so that I am able to to do cross domain requests?
Here is what worked for me.
http://flask-cors.readthedocs.org/en/latest/
$ pip install -U flask-cors
from flask import Flask
from flask.ext.cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route("/")
#cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
I got it working by adding
response.headers['Access-Control-Allow-Headers'] = "Origin, X-Requested-With,Content-Type, Accept" to the after_request() method.
For development you can:
Use Chrome extension - https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
Start chrome in unsecured mode - https://stackoverflow.com/a/3177718/1104483
Or just set Access-Control-Allow-Origin to *

Resources