Here is my simple endpoint:
#app.route('/test', methods=['POST'])
def test():
print(request.data)
return Response("", mimetype='application/json')
The request body is:
"ัะตัั"
And the server prints b'"\xd1\x82\xd0\xb5\xd1\x81\xd1\x82"' for request data.
How to set appropriate charset, providing content type header did nothing?
Also is there a way to get rid of that annoying b at the start of every request body?
For anyone having similar problem:
from flask import Flask
from flask import Response
from flask import reques
import chardet
#app.route('/test', methods=['POST'])
def test():
charset = chardet.detect(request.data)['encoding']
print(request.data.decode(charset))
return Response("", mimetype='application/json')
I was unable to make flask to this for me...
so you have to manually decode the bytes.
Related
I am new to python and flask and I am encountering a problem with Flask. I am trying to use a local HTTP POST (webhook) to call a function from another file, but when I do nothing happens.
from flask import Flask
from BotSpeak import main
app = Flask(__name__)
#app.route('/', methods=['POST'])
def respond():
main('hello')
if __name__ == '__main__':
app.run()
This is my very basic Flask app. As you can see it is trying to call the main function from this file (BotSpeak):
from json import dumps
from httplib2 import Http
def main(botmsg):
url = 'PLACEHOLDER FOR GOOGLE CHAT WEBHOOK URL'
bot_message = {
'text' : botmsg}
message_headers = {'Content-Type': 'application/json; charset=UTF-8'}
http_obj = Http()
response = http_obj.request(
uri=url,
method='post',
headers=message_headers,
body=dumps(bot_message),
)
print(response)
if __name__ == '__main__':
main("TEST MESSAGE")
This is the code that shoots local HTTP POSTs to my flask app:
import json
import requests
webhook_url ='http://127.0.0.1:5000/'
data = {PLACE HOLDER FOR JSON DATA}
r = requests.post(webhook_url, data=json.dumps(data), headers={'Content-Type': 'application/json'})
I can call the main function from other files outside the flask app and it'll work but it just wont trigger in the app.route decorator like it should. I really appreciate anyone's help and I encourage you to throw these into VS Code and try it for yourself.
If you're using flask you don't have to manually construct an HTTP response using httplib2 unless you have some very specific use case.
In your case you can just return bot_message since if the return value of a Flask handler is a dict it will convert it to a JSON response (including the correct headers). See
https://flask.palletsprojects.com/en/2.0.x/quickstart/#about-responses
In other words, your entire route handler could be rewritten (based off your example at least):
#app.route('/', methods=['POST'])
def respond():
return {'text': 'hello'}
If you want to pass the handling off to some utility function you can do that too, just make sure it returns a value, and that you in turn return an appropriate value from your respond() function.
I'm trying to send an xlsx file using Python requests library. My request looks like this:
import requests
url_attachment = "http://127.0.0.1:5000/api/attachment"
payload={}
files=[('file',(filename, open(filename,'rb'),'application/octet-stream'))
]
headers = {}
requests.request("POST", url_attachment, headers=headers, data=payload, files=files)
and my mock server looks like this:
import flask
from flask import request
app = flask.Flask(__name__)
app.config["DEBUG"] = True
#app.route('/', methods=['GET'])
def home():
return "<h1>Hello World</h1>"
#app.route('/api/attachment', methods=['POST'])
def get_file():
data = request.files['file']
data.save('the-file.xlsx')
return "ok"
app.run()
The mock server works fine, and the file gets sent correctly.
However, when I call the actual API (that I have no access to), the file gets corrupted. The person who owns the API sent me the corrupted file, and after inspection I can see that the content got wrapped in this:
-------------------------------28947758029299
Content-Disposition: form-data; name="the-file.xlsx"; filename="the-file.xlsx"
Content-Type: application/octet-stream
//content
-------------------------------28947758029299--
Does someone have an idea why this is happening? What can I change in my function to stop this from happening? I have also tried changing the Content-Type to application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet but apparently this results in the same problem.
This has been resolved now. If anyone comes across a similar issue in the future, the cause was the receiving method in the API considering content as 'multi-part form data'.
I have a RestApi developed in python using flask, the Api only supports HTTP request with Json format, so now I would like to identify unsupported request type in Python code.
I was trying to use
from flask import request
but how to check if its not a HTTP Json request? Any suggestions?
Usually the content type is declared in the request header. So using the request, you can check if such a header is present. For example:
#app.route('/',methods = ['POST'])
def add():
if request.headers['Content-Type'] == 'application/json; charset=UTF-8':
print (request.get_json())
return "json OK"
raise FailedRequest
I simplify my requirement to this simple code
from flask import Flask, request
import requests
app = Flask(__name__)
#app.route('/', methods=['POST'])
def root():
payload = {'Message': 'yo','Port':'123'}
r = requests.post("http://127.0.0.1:5000/test", data=payload)
return r.text
#app.route('/test', methods=['POST'])
def test():
return request.form['Message']+','+request.form['Port']
if __name__ == '__main__':
app.run(debug=True)
I've tested the url '127.0.0.1:5000/test' by google's Postman.
I send the data to the url, and It worked, can return the result I wanted.
And I created another .py to test the url, too. It also can show the result I wanted.
import requests
payload = {'Message':'yo','Port':'123'}
r = requests.post("http://127.0.0.1:5000/test", data=payload)
print r.text
Then I put the same code below
#app.route('/', methods=['POST'])
def root():
I want to use the url '127.0.0.1:5000/' to send data to the '127.0.0.1:5000/test' (I also Use google's Postman)
And it can't worked... it always show 'loading...'
Is there a better way to implement my requirement ?
I will thank you so so so much ~!!
Instead of sending a local POST request, which would take a lot longer time, just have them both route to the same function, and set defaults.
#app.route('/', methods=['GET'])
#app.route('/test', methods=['POST'])
def test():
return request.form.get('Message', 'yo') + ',' + request.form.get('Port', '123')
Which would respond normally to all POST requests on /test, and with a GET to /, it works the same as POSTing {'Message': 'yo', 'Port': '123'} to /test
I want to use flask to return JSON to the brower with or without simplejson (with appropriate headers) here is what I have so far for my flask application:
#app.route('/')
def hello_world():
QUERY_URL="http://someappserver:9902/myjsonservlet"
result = simplejson.load(urllib.urlopen(QUERY_URL))
return result;
Assuming the JSON output returned is:
{"myapplication":{"system_memory":21026160640.0,"percent_memory":0.34,
"total_queue_memory":4744,"consumers":1,"messages_unacknowledged":0,
"total_messages":0,"connections":1}
When I visit the page http://localhost:5000 however, I get a Internal Server Error. What must I do with "result" to get it to display appropriately? Or is there some way I can tell it to return with json headers?
When I add a print statement to print the result I can see the JSON, but in the browser it gives me an Internal Server Error.
import requests
r = requests.get(QUERY_URL)
return r.json
#normal return
return jsonify(username=g.user.username,
email=g.user.email,
id=g.user.id)
jsonify is available in flask. Here is the docs