I am trying to make a javascript request to a python backend rest, and getting errors I cannot resolve. I am trying to test if a listname is in a request.json object that I am passing through the axios data, but python either can't see it or throws an error.
Here is my python code:
#app.route('/', methods=['GET', 'DELETE', 'POST'])
def profits():
if request.method=='GET':
if 'listname' in request.json():
print 'inside listname == True!!!'
conn = psycopg2.connect(database = "profitnloss3", user = "patientplatypus", password = "*************")
cur = conn.cursor()
sql = 'SELECT * FROM ledger WHERE listname = %s'
params = (request.json['listname'])
cur.execute(sql, params)
conn.commit()
data = cur.fetchall()
conn.close()
return jsonify(data)
else:
print 'inside listname == False!!!'
conn = psycopg2.connect(database = "profitnloss3", user = "patientplatypus", password = "*******************")
cur = conn.cursor()
sql = 'SELECT * FROM ledger'
cur.execute(sql)
conn.commit()
data = cur.fetchall()
conn.close()
return jsonify(data)
The relevant line that is giving me trouble is if 'listname' in request.json():
Here is the axios call that I am making in the front end:
axios({
method: 'get',
url: 'http://localhost:5000/',
headers: {
'Content-type': 'application/json'
},
data:{
'listname': this.ledgername
}
})
.then((response)=>{
console.log('this is the response from the python server on a get request of listname ', response);
})
.catch(error=>{
console.log('here is the error on a get request from the python server of listname ', error);
})
The error that I am getting is:
TypeError: 'NoneType' object is not callable
If I instead use if 'listname' in request.json:
TypeError: argument of type 'NoneType' is not iterable
I have also tried using the form variable (ie request.form) but the values are then completely ignored from the axios post even though an error is not thrown (I guess it doesn't see it as form data).
I do not know where to go from here, any help would be appreciated.
EDIT:
My import header at the top of my python file is
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS, cross_origin
import sqlite3
import psycopg2
import os
from os.path import join, dirname
from dotenv import load_dotenv
from models.shared import db
from models.profits import Profit
I guess you are not sending the data at all because according to the axios documentation the data option is „Only applicable for request methods 'PUT', 'POST', and 'PATCH'“.
So you have to use a POST request (and change the server code accordingly):
axios({
method: 'post',
url: 'http://localhost:5000/',
headers: {
'Content-type': 'application/json'
},
data: {
'listname': this.ledgername
}
})
.then((response) => {
console.log('this is the response from the python server on a post request of listname ', response);
})
.catch((error) => {
console.log('here is the error on a post request from the python server of listname ', error);
});
or sending the listname as GET parameter instead of as JSON in the request body.
Related
The js I used to send a POST request
const formData = new FormData();
formData.append('textData', 'somestring');
formData.append('file', File object);
const request = {
method: "POST",
body: formData,
headers: {'Content-Type': 'multipart/form-data'},
};
const response = await fetch('http://localhost:8001/upload_files', request);
I can assure the formData object contains the data
My Python Flask API
app = Flask(__name__)
#app.route('/upload_files', methods=['POST'])
#cross_origin()
def upload_files():
print(request.form)
print(request.files)
if __name__ == '__main__':
app.run(debug=True, host='localhost', port=8001)
The print from the API function
ImmutableMultiDict([])
ImmutableMultiDict([])
The API can receive the POST request from the js but did not receive the data and file. How can I solve this problem? Many thanks!
The POST request works after I remove the content type. The content type is automatically set based on the FormData object
const request = {
method: "POST",
body: formData,
};
How do I send a json POST request using Javascript and read it on a flask server?
Last approach (reference):
const uploadjson = storeDictionary
const url = "/uploadset/"+setName
fetch(url, {method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: uploadjson})
.then((response) => response.json())
.then((data) => {
console.log('Success:', uploadjson);
})
.catch((error) => {
console.error('Error:', error);
console.log("Data:", uploadjson)
});
It results in the following error message:
Here's a part of the python code (flask) I wrote with help from the documentation:
#app.route("/uploadset/<name>", methods=['GET','POST'])
def uploads(name):
if flask.request.method == "POST":
print("Upload!")
if 'id' in flask.session:
if flask.session['id'] in client:
sessid = flask.session['id']
if name != "":
print("flask.request.files", flask.request.files)
file = flask.request.files['file']
try:
if processUploadedSet():
error = False
success = True
This results into a "server didn't understand your request".
I found out that the flask server is the problem:
Here's the server log:
If I return an empty string on the server the request works 'fine'.
How do I read json data using flask which was sent using the javascript?
You can read a json response in flask using flask.request.get_json
Simply replace file = flask.request.files['file']
with file = flask.request.get_json(cache=False)
Sending a json POST request is not the same as sending a file!
I have a python flask api app shown as below.
from flask import Flask, jsonify, request
from flask_cors import CORS, cross_origin
# creating a Flask app
app = Flask(__name__)
CORS(app,origins = ['*'],send_wildcard = True)
#app.route('/getapi', methods = ['GET'])
def api1 ():
return ({"text": "Hello World"})
#app.route('/putapi', methods = ['PUT'])
def api2():
formtext = request.form.get("inputtext")
return ({"text": formtext})
# driver function
if __name__ == '__main__':
app.run(debug = True)
I have a Javascript in an HTML page as below
async function getText() {
const api_url = "http://127.0.0.1:5000/getapi";
const api_req = new Request(api_url);
api_req.method = "GET";
const response = await fetch(api_req);
const data = await response.json();
console.log(data);
}
async function putText() {
const api_url = "http://127.0.0.1:5000/putapi";
const api_req = new Request(api_url);
const requestOptions = {
method: "PUT",
headers: { "Content-Type": "multipart/form-data" },
};
const formData = new FormData();
formData.append("inputtext", "new text from browser");
api_req.formData = formData;
const response = await fetch(api_req, requestOptions);
const data = await response.json();
console.log(data);
}
The webpage is run using a live server extension in VSCode and runs as http://127.0.0.1:5500/. Flask API is run as http://127.0.0.1:5000.
When I call the getapi, there is no CORS error. But when the script calls putapi, there is a CORS error in console
Access to fetch at 'http://127.0.0.1:5000/putapi' from origin 'http://127.0.0.1:5500' 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.
Why this inconsistent behaviour? I also did try changing the method to GET instead of PUT. Still same error. From HTML, the getapi is called first on body onload. On a button click, the putapi is called.
You aren't sending any request body. Your PUT request is malformed which is probably causing Flask to respond with an error, bypassing CORS configuration.
To correctly send a PUT request with multipart/form-data payload, use the following...
async function putText() {
const api_url = "http://127.0.0.1:5000/putapi";
const formData = new FormData();
formData.append("inputtext", "new text from browser");
const response = await fetch(api_url, {
method: "PUT",
body: formData,
});
const data = await response.json();
console.log(data);
}
Setting the request body to your FormData instance automatically sets the appropriate content-type header when sent from a browser.
Since you're not sending any binary data, you don't really need FormData. You could instead use URLSearchParams to send an application/x-www-form-urlencoded body
const response = await fetch(api_url, {
method: "PUT",
body: new URLSearchParams({ inputtext: "new text from browser" }),
});
or even just format the payload yourself but then you'd also need to supply the content-type header
const response = await fetch(api_url, {
method: "PUT",
body: `inputtext=${encodeURIComponent("new text from browser")}`,
headers: {
"content-type": "application/x-www-form-urlencoded",
},
};
I'm trying to create a simple website to run a neural network on an image. The frontend is in VUE.js and the backend in python flask. I can pass the data I want like id and precision in the header, however, the file doesn't "upload" to the flask server. Any idea how I should be doing this?
This is my method in javascript:
async predictUF(img) {
//let config = {header : {'Content-Type' : 'image/png'}}
const response = await fetch("http://localhost:5000/process_img", {
method: 'POST',
headers: {'id': '123', 'precision': '75'},
files: img,
mode: 'cors',
cache: 'default'
});
const recv = await response.json();
console.log(recv);
},
And this is my flask server code:
#app.route('/process_img', methods=['POST', 'GET'])
#cross_origin()
def process_image():
if request.method == 'POST':
filenames = []
payload = request.headers
id = payload['id']
precision = payload['precision']
files = request.files.to_dict(flat=False)
for file_list in files.values():
for file in file_list:
name = secure_filename(file.filename)
path = save_image(file, name)
filenames.append(path)
results, img_paths = run_process(filenames)
encoded_imgs = [encode_image(p) for p in img_paths]
return jsonify({'msg': 'success', 'results': [results], 'images': encoded_imgs})
else:
return 'Methods restricted'
I had a python script to test the api that worked perfectly, it was something like this (I ignored the base64 encodings on purpose to simplify the problem):
r = requests.post(url, files=files, data=payload)
Is there any way to fill the files in the javascript fetch api or am I getting this all wrong?
Thanks to Ibsn I got it working.
For flask to accept request.files: an HTML forms must be used with enctype=multipart/form-data. (How do I upload a file with the JS fetch API?)
Fortunately, javascript FormData() uses the same format a form would use if the encoding type were set to "multipart/form-data". So my final js working version is this. (Get the data received in a Flask request)
async predictUF(img) {
var data = new FormData();
data.append('files', img, img.name);
const response = await fetch("http://localhost:5000/process_img", {
method: 'POST',
headers: {'id': '123', 'precision': '75'},
body: data,
mode: 'cors',
cache: 'default'
});
const recv = await response.json();
console.log(recv);
},
I'm invoking an authentication service via javascript fetch to get an access token. The service is a simple RESTful call. I can see the call is successful using fiddler (with a 200 response and json data). However the fetch response never seems to get invoked. Below is a snippet:
const AUTHBODY = `grant_type=password&username=${username}&password=${password}&scope=roles offline_access profile`
const AUTHHEADER = new Headers({'Content-Type': 'application/x-www-form-urlencoded'})
const CONFIG = {
method: 'POST',
headers: AUTHHEADER,
body: AUTHBODY
}
fetch('http://localhost:23461/connect/token', CONFIG).then(function(response) {
console.log('response = ' + response)
return response.json()
}).then(function(json) {
console.log('json data = ' + json)
return json
}).catch(function(error) {
console.log('error = ' + error)
})
When executing the fetch above none of the console.logs gets executed... seems to just hang. But fiddler tells otherwise. Any ideas?
You probably met with the CORS origin policy problem. To tackle this you need some rights to access the server side of your API. In particular, you need to add a line in the header of php or another server endpoint:
<?php
header('Access-Control-Allow-Origin: *');
//or
header('Access-Control-Allow-Origin: http://example.com');
// Reading JSON POST using PHP
$json = file_get_contents('php://input');
$jsonObj = json_decode($json);
// Use $jsonObj
print_r($jsonObj->message);
...
// End php
?>
Also, make sure NOT to have in the header of your server endpoint:
header("Access-Control-Allow-Credentials" : true);
Model of working fetch code with POST request is:
const data = {
message: 'We send a message to the backend with fetch()'
};
const endpoint = 'http://example.com/php/phpGetPost.php';
fetch(endpoint, {
method: 'POST',
body: JSON.stringify(data)
})
.then((resp) => resp.json())
.then(function(response) {
console.info('fetch()', response);
return response;
});