Access json content of http post request with Klein in python - python

I have a simple http client in python that send the http post request like this:
import json
import urllib2
from collections import defaultdict as dd
data = dd(str)
req = urllib2.Request('http://myendpoint/test')
data["Input"] = "Hello World!"
response = urllib2.urlopen(req, json.dumps(data))
On my server side with Flask, I can define a simple function
from flask import request
#app.route('/test', methods = ['POST'])
def test():
output = dd()
data = request.json
And the data on server will be the same dictionary as the data on the client side.
However, now I am moving to Klein, so the server code looks like this:
#app.route('/test', methods = ['POST'])
#inlineCallbacks
def test(request):
output = dd()
data = request.json <=== This doesn't work
and the request that's been used in Klein does not support the same function. I wonder is there a way to get the json in Klein in the same way I got it in Flask? Thank you for reading this question.

Asaik Klein doesn't give you direct access to the json data, however you can use this code to access it:
import json
#app.route('/test', methods = ['POST'])
#inlineCallbacks
def test(request):
output = dd()
data = json.loads(request.content.read()) # <=== This will work

Related

My #app.route decorator is not triggering its function

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.

Flask server can't read cyrillic requests

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.

Python Flask, connect another url

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

How to get json data from another website in Flask?

I want to make a website with Flask to show some data posted from another website such as this one.In short,I want to list the data from that website.
Should I use this method: flask.Request.get_json()?
I do not know how to get a Request object. Could you show me some demos about that?
I am using Python 3 and Flask.
import requests
def get(url):
try:
res = requests.get(url)
return res.json()
except:
return False
data = get('http://example.com')
print(data)
In short,I want to list the data from that website.
The accepted answer seem not use flask, so I'll add some:
from flask import jsonify, Flask
import requests
app = Flask(__name__)
#app.route('/')
def index():
r = requests.get('https://api.github.com/users/runnable')
return jsonify(r.json())
Should I use this method: flask.Request.get_json()
No, it is for parsing the incoming json request data. No one is sending requests to you.

[Python-Webservice]: How to return and consume on XML format on Flask

I am currently creating a RESTful webservice in python utilizing flask. Now on the client side that will use / implement the webservice APIs, I want to get the output in XML (or JSON) format. Do you have any ideas on how to do this? I already tried jsonify but no success. Also, i prefer an XML format in output, but again, I don't know how to do it. So I hope someone can give me ideas.
Below are dummy code snippets to hopefully clarify my question:
/*** webservice ***/
from flask import Flask, jsonify
app = Flask(__name__)
#app.route("/")
def hello_world():
return jsonify(message = "hello world!")
if __name__ == "__main__":
app.run()
/*** client code ***/
import urllib2
server = "http://localhost:5000/"
req = urllib2.Request(server)
# req has no data at all :(
Hoping to receive feedback. Than=ks in advance
The server code runs fine. You should test it with a normal web browser and you will see the json response. Your client code isn't complet. There my correction:
import urllib2
server = "http://localhost:5000/"
req = urllib2.Request(server)
response = urllib2.urlopen(req)
print response.read()
A better way to do http requests in python is to use the requests module which provides a very simple but very powerful api.
import requests
res = requests.get("http://localhost:5000/")
print res.text
To build xml response I would recommend lxml with his cool etree modul. There is also a etree modul in the standart lib under xml.etree.

Categories

Resources