I am trying send json in request post to python using cherrypy. When I send the request, the response is (400 bad request, Invalid JSON document), nevertheless using postman i make the same request and the server return the result withou errors.
My python code:
import time, sys, cherrypy, os
import json
import ML_Training
import ML_Unsup_Predictor_Results
class Application(object):
#cherrypy.expose
#cherrypy.tools.json_in()
def predict(self):
try:
cherrypy.response.headers["Access-Control-Allow-Origin"] = "*"
cherrypy.response.headers['Content-Type'] = "application/json"
input_json = cherrypy.request.json
r = ML_Unsup_Predictor_Results.Predict_New_Values(input_json["model"], input_json["value"])
return json.dumps(r)
except Exception as e:
print e.message
return e.message
In javascript my request post using angularjs
$http.post(mlService.getMlMultitenancyOrigin() + '/python/predict',
{"model":$scope.params[2], "value": arr}).then(function(result){
console.log(result);
})
note: the structure of arr is arr = [1,2,3,4] (array of integers)
My question is why "invalid JSON"
attached image of postmant, when the result is ok
Related
This question already has answers here:
How to get POSTed JSON in Flask?
(13 answers)
Closed 2 days ago.
I was trying to send some JSON data to the sever following some online articles and the official flask documentation, but I keep getting a 400 error. What I've tried hasn't worked so far.
I have read that if flask doesn't get properly formated JSON data it pushes this error and also that the read of the request must specify Content-Type header as application/json or else the same happens.
I copied some of my code off the official Documentation and this is what i have so far:
a view function inside my flask application:
#main.route('/test', methods=['GET','POST'])
def test():
if request.method == 'POST':
print(request.method)
print(request.headers.get('Content-Type'))
print(request.is_json)
#this gets me the 400 when run
#print(request.json)
return render_template('test.html')
the following scrip tag inside test.html:
<script>
let data = {"data": "Hello World!"}
document.querySelector('#main').addEventListener('click', function () {
fetch('/test', {
method: "POST",
body: JSON.stringify(data),
headers: {"Content-Type": "application/json"},
credentials: "same-origin"
})
.then(response => console.log(response.json))
})
</script>
Every time I hit the button to POST the data I get the following showing in my terminal
POST
text/plain;charset=UTF-8
False
So I assume what is causing all of this is that the Content-Type header of the HTTP request is not setting properly.
Any ideas on how I could fix this would be apreciated
Based on your code and the error message you are receiving, the issue might be related to the request header not being set correctly.
You are setting the Content-Type header in your JavaScript code to "application/json", which is correct. However, your Flask view function does not check the Content-Type header correctly. You can check it like this:
if request.is_json:
data = request.get_json()
print(data)
else:
print("Request is not JSON")
This checks whether the request is in JSON format using the is_json property of the request object. If it is, then you can use the get_json() method to extract the data. If it's not, you can print a message or return an error.
Additionally, you might want to add a try-except block to catch any errors that might occur when parsing the JSON data:
if request.is_json:
try:
data = request.get_json()
print(data)
except Exception as e:
print("Error parsing JSON data:", e)
return "Bad Request", 400
else:
print("Request is not JSON")
return "Bad Request", 400
This will catch any exceptions when parsing the JSON data and return a "Bad Request" error with a 400 status code.
I hope this helps!
You need to specify the full endpoint of what you are targeting.
from flask import Flask, request
# create the flask app
app = Flask(__name__)
# post endpoint
#app.route('/post', methods=['POST'])
def endpoint():
data = request.get_json()
return data
# run the app
if __name__ == '__main__':
app.run(debug=True)
const endpoint = "http://127.0.0.1:5000/post";
// post request to endpoint
const response = fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "John Doe",
})
});
response.then(data => {
data.text().then(text => {
console.log(text);
})
})
I have an old application based on Python SimpleHTTPServer that I'm trying to convert to Flask.
In the old application, I had an HTML form that was submitting a POST request to the SimpleHTTPServer. The form also had an iframe. There, I had a do_POST method that was reading the values in the text boxes and producing some results. I then wrapped the results into a JSON object and wrote to the wfile method of SIMPLEHTTPServer. This caused the result to get populated into the iframe. The iframe had an onload method on the JS side and here, the results would be read from it and populated into various text-boxes.
I now want to convert this to Flask from SimpleHTTPServer. What is the best way to translate the logic I have in place to Flask? Basically, what is the equivalent of writing to the wfile object?
Also, on the Flask side, I also have some #app.route methods where I can form a URL with input parameters and get the results as JSON objects (example: http://localhost/calculate?input1=3&input2=5). Is it possible to leverage these URLs instead of the POST request to get the result into JavaScript?
Here is hello world of flask to get the data from URL parameters and do the stuff and return a json
from flask import Flask, jsonify, request
app = Flask(__name__)
#app.route('/')
def hello_world():
param1 = request.args.get('param1')
param2 = request.args.get('param2')
res = param1 + param2
return jsonify({
"result": res
})
if __name__ == '__main__':
app.run()
example request
GET http://127.0.0.1:5000/?param1=hi¶m2=there
Example response
{
"result": "hithere"
}
I have looked all over Stack Overflow but I have not found an answer to this question.
How can a python script dynamically receive a url based on a javascript function call?
For example, in this Stack Overflow question (Code reproduced below) how could I dynamically receive the url (which is hardcoded in this case) if the name of the python file was abc.py and I called
xhttp = new XMLHttpRequest(); and then
xhttp.open("GET", "abc.py?token=123", true); in some html file with javascript?
from urllib.parse import urlparse
from urllib.parse import parse_qs
from urllib.parse import urlencode
url = 'http://example.com?param1=a&token=TOKEN_TO_REPLACE¶m2=c'
o = urlparse(url)
query = parse_qs(o.query)
if query.get('token'):
query['token'] = ['NEW_TOKEN', ]
new_query = urlencode(query, doseq=True)
url.split('?')[0] + '?' + new_query
>>> http://example.com?param2=c¶m1=a&token=NEW_TOKEN
You need to use framework to do this, python script alone with no networking/socket functionality could not communicate with the front-end (js side), below is a simple backend to received your javascript request using bottle.py
Here is a simple implementation that receives a POST request from client and do the logic you need, updated url is returned to the calling code.
Note the request is POST and the data is json with the token and url
from bottle import post, run, request
import json
from urllib.parse import urlparse
from urllib.parse import parse_qs
from urllib.parse import urlencode
def replace_token(data):
url = data['url']
token = data['token']
o = urlparse(url)
query = parse_qs(o.query)
if query.get('token'):
query['token'] = [token]
new_query = urlencode(query, doseq=True)
return url.split('?')[0] + '?' + new_query
#post('/token')
def index():
data = json.load(request.body)
return replace_token(data)
run(host='localhost', port=8080, debug=True)
Then you can test it by simple using a curl
curl -X POST http://localhost:8080/token -d '{"token":"NEW_TOKEN", "url":"http://example.com?param1=a&token=TOKEN_TO_REPLACE¶m2=c"}'
Is there a way to return a response (from make_response() object or similar) with certain properties so that it doesn't render the page again and doesn't do anything else either. I am trying to run a code on the server without generating any output
A simple 'return None' produces:
ValueError: View function did not return a response
This should be possible because the following only downloads a file and doesn't render the template:
myString = "First line of a document"
response = make_response(myString)
response.headers["Content-Disposition"] = "attachment; filename=myFile.txt"
return response
You are responding to a request, your HTTP server must return something. The HTTP 'empty response' response is 204 No Content:
return ('', 204)
Note that returning a file to the browser is not an empty response, just different from a HTML response.
Use Flask Response
with status 204 (no content)
from flask import Response
return Response(status=204)
I'm writing a small app. Here is the code snippet.
Javascript:
<script type="text/javascript">
function filldata()
{
var sample = document.getElementById("filter-select").value;
jQuery.support.cors = true;
$.post("/test",{"filter_type":sample},function(data,status)
{
alert(data);
});
}
</script>
Flask Code:
#app.route('/test', methods=['POST'])
def test(str):
return str
It is giving me 500 internal error.
When I run this in debug mode, it is saying:
test() takes exactly one argument(zero given)
Your code:
#app.route('/test',methods=['POST'])
def test(str):
return str
Expect a variable named str in input.
With flask, when defining route the arguments of the function represent the url variables:
# the url have a parameter
#app.route('/user/<id>',methods=['GET'])
def test(id): # we get it here
return user.fromId(id)
To retrieve querystring you can use request.args. And to get body request.data or request.json if you are sending json.
from flask import request
#app.route('/test',methods=['POST'])
def test():
return request.data
You need to parse argument from Flask's request object
from flask import request
#app.route('/test',methods=['POST'])
def test():
return request.form.get('filter_type')
See quickstart for more info
In your Flask code snippet, you have added an argument, but arguments are only sent if you change the URL to /test/<str:str>. Since it is a POST request, you can access the data by using request.json.