python service access to ajax call , CORS error - python

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');
}
});

Related

"opaque" response from FLASK API

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);
});
};

Post request from react to flask

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

No 'Access-Control-Allow-Origin' header is present on the requested resource (FLASK API / ReactJs)

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)

How to use Flask development server successfully with Ajax post request?

I'm currently using Flasks's development server instead of using a separate one because I don't need the extra bulk. My server will not be processing many requests at once, so I feel the development server is fine enough.
What I'm Trying To Do
I have a python script that I'm trying to run with the click of a button on a web page. This web page is run on an Apache 2 web server on Ubuntu.
What I've Done
I've installed Flask and tried to post to my python script, but I always get this error:
* Serving Flask app "ResetPOE" (lazy loading)
* Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: on
It always returns to my error block in my Ajax request and never to my success block. I do not get any return JSON from my Python script. I just want to know whether or not my script ran, I don't necessarily need any output from the script itself.
P.S. my Python may be incorrect, but I haven't even gotten it to recognize it yet, so that's been on the back burner for now. I'm just trying to get the post request to be successful.
ajax.js
function ajaxCall(input) {
var data = {"param" : input};
$.ajax({
url: "/cgi-bin/reset.py/request",
type: "POST",
contentType: "application/json",
data: JSON.stringify(data),
dataType: 'json',
success: function(response){
console.log("success");
console.log(response);
},
error: function(xhr, status, error) {
console.log("error");
var err = xhr.responseText;
console.log(err);
}
});
}
reset.py
#!/usr/bin/python3
print("Content-type: text/html")
print ("")
from flask import Flask, request, jsonify
import json
app = Flask(__name__)
#app.route('/')
def sendOK(environ, start_response):
status = '200 OK'
output = "Hello World!"
response_headers = [('Content-type', 'text/plain'),('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
#app.route('/request', methods=['POST'])
def processRequest():
data = request.form["param"]
# other code to do stuff with the data...
return Response(json.dumps({"status":"success"}), mimetype="application/json")
if __name__=="__main__":
app.run(debug=True, threaded=True, host="192.168.1.101")
It returns a 200 (OK) in my browser, but I'm not getting any return values, and I can tell my error block is executing and not my success block.

Making POST requests to Flask and getting back data

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

Categories