I am trying to send a post request from react to flask using the following code:
function App() {
const [currentTime, setCurrentTime] = useState(0);
const [accessToken, setAccessToken] = useState(null);
const clicked = 'clicked';
useEffect(() => {
fetch('/time').then(res => res.json()).then(data => {
setCurrentTime(data.time);
});
}, []);
useEffect(() => {
// POST request using fetch inside useEffect React hook
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'React Hooks POST Request Example',action: 'clicked' })
};
var myParams = {
data: requestOptions
}
fetch('http://127.0.0.1:5000/login', myParams)
.then(response => response.json())
.then(data => setAccessToken(data.access_token));
// empty dependency array means this effect will only run once (like componentDidMount in classes)
}, []);
return (
<div className="App">
<div className="leftPane">
<div className="joyStick" >
<Joystick size={300} baseColor="gray" stickColor="black" ></Joystick>
</div>
<p>The current time is {currentTime}.</p>
<p>The access token is {accessToken}.</p>
</div>
And the flask code is
from __future__ import print_function
from flask import Flask, jsonify, request
from flask_cors import CORS
import time
from flask import Flask
import sys
robotIP="10.7.4.109"
PORT=9559
app = Flask(__name__)
access_token='a'
action="d"
#app.route('/time')
def get_current_time():
return {'time': time.time()}
#app.route('/login', methods=['POST'])
def nao():
nao_json = request.get_json()
if not nao_json:
return jsonify({'msg': 'Missing JSON'}), 400
action = nao_json.get('action')
access_token= action+'s'
print(access_token, file=sys.stderr)
return jsonify({'access_token': access_token}), 200
But every time I run both them both, I get the 'msg': 'Missing JSON' message I have defined and the data from react is never available in flask,even though the get request works.I am not sure what I am doing wrong here.
The problem actually is that this is a cross origin request which must be allowed by the server.
Place this function on your Python code:
#app.after_request
def set_headers(response):
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Headers"] = "*"
response.headers["Access-Control-Allow-Methods"] = "*"
return response
Note:
If react is served from the same server this won't be necessary.
You should set the value of these headers to be as strict as possible on production. The above example is too permissive.
You could serve your React aplication from Flask, thus not requiring these headers to be set. You could use something like this to serve the main react file:
#app.route('/', defaults={'path': ''})
#app.route('/<string:path>')
#app.route('/<path:path>')
def index(path: str):
current_app.logger.debug(path)
return bp_main.send_static_file('path/to/dist/index.html')
Where path/to/dist/index.html would be on the static folder.
See more at:
MDN Web docs
Stackoverflow: How to enable CORS in flask
Stackoverflow: Catch all routes for Flask
Related
So currently I am developing a very minimal front-end using react. I am very much a beginner with react. I created a dummy API at using FLASK which was returning json string. The problem is that I recieve the response on front-end. But the type is "opaque". I am currently in development mode and the connection is not secure obv. So I believe the issue is with security. Is there any workout for this in dev mode?
I am attaching screenshot of response and code of front-end and backend as reference.
Thank you for help in advance.
I tried: FLASK CORS method as mentioned in the code.
I was expecting to catch JSON at frontend but it gives error. The error is in response.json() line in js code. error
from flask import Flask, request, jsonify
from flask_cors import CORS
import os
import base64
from PIL import Image
import numpy as np
from flask import send_file
app = Flask(__name__)
cors=CORS(app, origins=["http://example.com", "http://147.46.246.106:3000"])
#app.route('/skinai', methods=['POST'])
def v1_launch():
response = jsonify({"recieved": "Tsdce"})
return response
if __name__ == '__main__':
#data={"some":"dummy"}
app.run(host='0.0.0.0', port=3336)
Frontend code:
fetch(host+'/skinai', {
method: 'POST',
body: formData,
mode: 'no-cors',
})
.then(response => {
console.log(response);
return response.json();
})
.catch(error => {
console.error('Error:', error);
});
};
I'm getting lost with this problem,
i have a service written in python that i need to access from a web page with an ajax call
the python code is as follows:
import flask
from flask import request, jsonify, make_response
from flask_cors import CORS, cross_origin
from datetime import datetime, timedelta
app = flask.Flask(__name__)
app.run(host='0.0.0.0', port=5000)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route('/api/v1/resources/device/all', methods=['GET'])
#cross_origin()
def api_all():
[...]
response = jsonify(result)
response.headers.add("Access-Control-Allow-Origin", "*")
return response,status_code
and the ajax call is:
$.ajax({
type: 'get',
crossDomain: true,
dataType: "json",
url: AddressWS + '/api/v1/resources/device/all?type=A',
success: function (result) {
//.,...
}
});
The error is ever
... has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource.
the web application is under IIS .
the question is :
if I set 0.0.0.0 as address in python script, which address should I call in the web application ?
i try to machine ipv4 address but don't run.
how i fix the cors problem, i seem to have correctly included the flask libraries.
Thanks everyone for the kind replies
CORS is not configured properly in your code. Please find below the code with the correct CORS configuration.
import flask
from flask import request, jsonify, make_response
from flask_cors import CORS
from flask_restful import Api
from datetime import datetime, timedelta
app = flask.Flask(__name__)
api = Api(app)
CORS(app)
#app.route('/api/v1/resources/device/all', methods=['GET'])
def api_all():
[...]
response = jsonify(result)
status_code = 'some code'
return response,status_code
if __name__ == '__main__':
app.run()
Try this in my case it works ,
$.ajax({
type: 'get',
dataType: 'json',
url: AddressWS + '/api/v1/resources/device/all?type=A',
cors: true,
contentType: 'application/json;charset=UTF-8',
secure: true,
headers: {
'Access-Control-Allow-Origin': '*',
},
success: function (result) {
//.,...
},
error: function (errorMessage) {
console.log('error');
}
});
I'm implementing a vegetable retail price predicting web application for one of my university projects using Flask and ReactJs. My POST requests work fine on Postman, but when I try to use a form in ReactJs to make a POST request, I get the following error:
Access to fetch at 'http://127.0.0.1:5000/vegetable' from origin 'http://localhost:3000' 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.
api_calls.js:7 POST http://127.0.0.1:5000/vegetable net::ERR_FAILED
Uncaught (in promise) TypeError: Cannot read property 'predicted_retail_price' of undefined
at Pricing.jsx:102
TypeError: Failed to fetch api_calls.js:22
API Results:::: undefined Pricing.jsx:101
But I have added following code segment in my server.py:
from flask import Flask, jsonify
from routes.lstm_price_route import lstm_price_blueprint
from routes.lstm_route import lstm_blueprint
from flask_cors import CORS, cross_origin
import csv
import json
server = Flask(__name__)
CORS(server)
server.config.from_object('config')
server.config['JSON_AS_ASCII'] = False
server.config['CORS_HEADERS'] = 'Content-Type'
server.register_blueprint(lstm_blueprint)
server.register_blueprint(lstm_price_blueprint)
The method in my Flask app(lstm_price_model.py):
def get_tomato_prediction(self, centre_name, date):
Data = pd.read_csv('lstm_price_prediction_tomato.csv')
result = {
'predicted_retail_price': Data.loc[(Data['centre_name'] == centre_name) & (Data['date'] == date), 'predicted_retail_price'].values[0]}
return jsonify(result)
The fetch call in React.js app(api_calls.js):
export const getPredictedPrice = async (centreName, pDate, vegetable) => {
try {
let price_prediction = await fetch(
`${BASE_URL}/vegetable`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
centre: centreName,
date: pDate,
commodity: vegetable
})
}
);
let result = await price_prediction.json();
return result;
} catch (error) {
console.log(error);
}
};
Github link for the frontend code - https://github.com/HashiniW/CDAP-F
Github link for the backend code - https://github.com/HashiniW/CDAP-B
Any suggestions to overcome this error? Thank You!
Try using mode: "no-cors" on the fetch frontend.
export const getPredictedPrice = async (centreName, pDate, vegetable) => {
try {
let price_prediction = await fetch(
`${BASE_URL}/vegetable`,
{
//Adding mode: no-cors may work
mode: "no-cors",
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
centre: centreName,
date: pDate,
commodity: vegetable
})
}
);
let result = await price_prediction.json();
return result;
} catch (error) {
console.log(error);
}
};
Use following code in your python project :
from flask import Flask, jsonify
from routes.lstm_price_route import lstm_price_blueprint
from routes.lstm_route import lstm_blueprint
from flask_cors import CORS, cross_origin
import csv
import json
server = Flask(__name__)
cors = CORS(server , resources={r"/*": {"origins": "*", "allow_headers": "*", "expose_headers": "*"}})
server.register_blueprint(lstm_blueprint)
server.register_blueprint(lstm_price_blueprint)
I am trying to connect my flask api to my react app and all I want from that is to display the string I returned from the flask on react app.
In doing so, I used useEffect(), but my variable in react is not changed but just keeps the original state. When I use console.log to see the value that I am passing to the variable, it shows an error saying "Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0".
App.js looks like:
import React, {Component, useState, useEffect} from 'react';
import './App.css';
function App() {
const [block, setBlock] = useState(0);
useEffect(() => {
fetch('/video').then(res => res.json()).then(data => {
setBlock(data.text);
console.log(data.text);
});
}, []);
return (
<div className="App">
<header className="App-header">
<p>Text: {block}</p>
</header>
</div>
);
}
export default App;
part of flask(flask.py):
#app.route('/video')
def video():
return {'text': text}
Any insight would be greatly appreciated!
If you want to return JSON from a Flask route use flask.jsonify.
from flask import jsonify
#app.route('/video')
def video():
return jsonify({'text': text})
I have a React app that makes a POST request to a Flask backend. The POST request is designed to alter some data in a database and send back a calculated value. Everything seems to work on the Flask side except for the response. The response I get from Flask is:
Response { type: "cors",
url: "http://127.0.0.1:3122/update",
redirected: false,
status: 200, ok: true, statusText: "OK", headers: Headers, bodyUsed: false }
I'm not sure what I'm doing wrong. In my Flask code, I use in the function decorated by #app.after_request
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,text/plain')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
and also the flask_cors package to allow for CORS from the client side.
app = Flask(__name__)
app.config['DEBUG'] = True
api = CORS(app, resources={r"/*": {"origins": "*"}})
I've also tried to set the mimetype in my response from Flask to be text/plain so a pre-flight request isn't invoked.
resp = Response(response=calculation_json,
status=200,
mimetype='text/plain')
The POST request code is:
(async () => {
const rawResponse = await
fetch(url, {
method: 'POST',
headers: {
'Accept': 'text/plain',
'Content-Type': 'text/plain'
},
body: jsonData
});
const response = await rawResponse;
if (response.status >= 200 && response.status < 300) {
console.log(response);
return Promise.resolve(response)
} else {
this.props.form.resetFields();
return Promise.reject(new Error(response.statusText))
}
In case if for client side of your application you have use create-react-app, you can add a proxy configuration in package.json file.
"proxy": {
"/apiRoute": {
"target": "http://127.0.0.1:3122"
},
},
The /apiRoute is the name of the routes (GET, POST, PUT..) you had defined in Flask. So i would suggest to make a pattern in Flask for all routes like /api/**, so in package.json instead of adding all routes, you can something like below
"proxy": {
"/api/*": {
"target": "http://127.0.0.1:3122"
},
},
You would have to change your response code such that it returns data not just regular http 200. In this case looks like you want Json back.
See the examples:
Return JSON response from Flask view