Python+Flask : how to get text from request with newlines? - python

I am not sure how it works, but it worked in one of my projects and doesn't works in a new one.
Obviously, I am missing something.
I want a simple REST server with only one POST.
It should get text from POST request. Text contains newlines.
This is my text.txt:
hello
how are you
This is how I test it:
curl -i -s -X POST -d #test.txt http://*ip*:*port*/api/gogogo
This is part of my python script with flask app:
#app.route('/gogogo', methods=['POST'])
def translate():
request_str = request.get_data().decode('utf-8').strip()
request_lines = request_str.split('\n')
print(request_lines)
return "yeah"
But "print(request_lines)" prints "hellohow are you".
Any ideas?
I also tried to use instead of '\n', didn't help. And even if it did - my requests use '\n', so i have to support this format.

Your problem is curl. It removes new line when you send it with -d.
You have to use --data-binary
curl -X POST --data-binary #test.txt http://localhost:5000/gogogo
BTW: you can test requests also with page https://httpbin.org which sends back as JSON all data which it get in request from you - headers, body, post data, url arguments.
It will also send back string without \n if you use -d instead of --data-binary
curl -X POST -d #test.txt https://httpbin.org/post
curl -X POST --data-binary #test.txt https://httpbin.org/post
BTW: Now it may send it with \r\n instead of \n but maybe it depend on system and how it keep new line in file. Better use .splitlines() instead of .split('\n')

try this
request_str = request.get_data().decode('utf-8').strip()
request_lines = request_str.splitlines(True)
for line in request_lines:
print(line)

Related

Bad JSON formatting in Jupyter API PUT call - error 400

I am quite new in python and can't understand why I am getting this 400 error. It seems like JSON formatting is wrong in the PUT call.
I have this dataframe.
And I am trying to run this code
url = "https://api.name.com/pacing-strategy"
for row in df_call_put.itertuples():
qs_li_id = {'line_item_id':row.line_item_id, 'member_id':1111}
payload_li_ps = [{'line_item_id':row.line_item_id,
'pacing_strategies':
[{'strategy_type': 'intelligent',
'when': 'ALWAYS'}]}]
rs_li_ps = requests.put(url, data=json.dumps(payload_li_ps) ,headers=headers, params=qs_li_id)
It should be just fine (exactly formatted like other PUT call I use) but it returns "
'errorCode': 400, 'errorDescription': 'Parameter line_item_id is invalid.'
As a comparison I ran the exact same thing in postman and it works fine, I however need it in a script so I have to use it in Jupyter.
One lead that could help you to find the solution. In Terminal I managed to make it work switching code from
curl -b cookies -c cookies -X PUT -H 'Content-Type: application/json' -d #always_asap.json "https://api.name.com/pacing-strategy?line_item_id=12345678"`
to
curl -b cookies -c cookies -X PUT -d #always_asap.json 'https://api.name.com/pacing-strategy?line_item_id=12345678&member_id=1111'
So it seems like the JSON reformatting with Content type was the issue.
Thanks!
I tried to remove json.dumps in the PUT call
I tried to change payload_li_ps code removing [] at the beginning.
We should get a OK status 200 but we have a 400 error

Submitting Python file in batch mode in Livy(without Hadoop installed)

i have made a simple python file which want to submit in Livy.Livy is currently running in local mode.Also I have mentioned following property in livy.conf file.
Property name: livy.file.local-dir-whitelist,
value "/usr/local/livy/scripts"
My file is kept in following path "/usr/local/livy/scripts"
import json, pprint, requests, textwrap
host = 'http://localhost:8998'
data = {'kind': 'spark'}
headers = {'Content-Type': 'application/json'}
r = requests.post(host + '/sessions', data=json.dumps(data), headers=headers)
r.json()
I am submitting it using curl as follows:
curl -X POST --data '{"file": "/usr/local/livy/scripts/pi.py"}' -H "Content-Type: application/json" 10.140.178.24:8999/batches
It is giving me following error:
requirement failed: Local path /usr/local/livy/scripts/pi.py cannot be added to user sessions.
My Ubuntu system only have following things:
a)Spark
b)Livy
c)Java
What am I doing wrong here?
For people using incubating mode of livy for first time,kindly check that the template file is renamed with stripping off .template in livy.conf.template.Then make sure that the following configurations are present in it.
livy.spark.master = local
livy.file.local-dir-whitelist = /path/to/script/folder/
Kindly make sure that forward slash is present in end of path
Then write url in following manner for
Python:
curl -v -X POST --data '{"file": "/path/to/script/folder/name-of-python-file.py"}' -H "Content-Type: application/json" localhost:8998/batches
Note:It will not accept relative path,whole absolute path needs to be defined in it.
curl -X POST --data '{"file": "/usr/local/livy/scripts/pi.py"}' -H "Content-Type: application/json" 10.140.178.24:8999/batches
{"id":2,"state":"starting","log":[]}

Get raw POST payload in Flask

I am sending text by cUrl
curl -X POST -d "Separate account charge and opdeducted fr" http://192.168.50.8/text
and try to get
#application.route("/text",methods=['POST'])
def clausIE():
content = request.data
text = str(content, encoding="utf-8")
But get empty string, what I am doing wrong?
Note: I use Python3.6
This is not really a Flask problem, you are using the wrong curl options.
The -d switch should only be used for form data. curl automatically will set the Content-Type header to application/x-www-form-urlencoded, which means that Flask will load the raw body content and parse it as a form. You'll have to set a different Content-Type header manually, using -H 'Content-Type: application/octet-stream' or another mime-type more appropriate to your data.
You also want to use --data-binary, not -d (--data), as the latter also tries to parse the content into key-value fields and will remove newlines:
curl -X POST -H 'Content-Type: application/octet-stream' \
--data-binary "Separate account charge and opdeducted fr" \
http://192.168.50.8/text
The complete answer seems to be scattered around some comments and the accepted reply. So to summarize this, the Python Flask code should look like
#application.route("/text",methods=['POST'])
def clausIE():
content = request.get_data()
text = str(content, encoding="utf-8")
return text
and this is what you should have at your terminal
curl -X POST --data-binary "Hello World!" http://192.168.50.8/text
At my own setup (OS X) I am allowed to drop -X POST and to wrap the URL around quotes, so that gives
curl --data-binary "Hello World!" "http://192.168.50.8/text"

Flask multidict mapping causing error

I'm sending a POST request via terminal to my flask backend server by doing the following:
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{“Email”:”email#email.com”,”Password”:”testpass”}' http://127.0.0.1:5000/auth/login
I can print out the request data in flask by doing the following:
print(request.data)
However, when I try to input the data into a form to validate the information, the process comes to a halt and fails.
I'm pretty sure the issue is caused by this code, since nothing gets executed after this line:
data = MultiDict(mapping=request.json)
Any idea why?
I'm not sure that your quotes are all the same in your curl command. I tried adapting that to one of my apis and it returned an error. Are you using the right quotes in your json? Are those smart quotes? I was able to replace them and it worked.
curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"email":"email#email.com","password":"testpass"}' http://127.0.0.1:5000/auth/login
If you are then taking the dictionary and then loading them into a form (form = LoginForm(**data)) you also need to make sure your keys match the naming of your form. I see in your json you have Email with E uppercase. Make sure that is the name of the form field in your form. If it is email = StringField(...) it won't map.

Python - json loads request parameter

I'm passing a json in my request data body as follow:-
curl --data "data={"applist":{"ads":{"ad":[{"adsid":1,"view_points":25,"view_type":"full","comment":"Success"}]}}}" POSTURL
Upon json loads, it throws an error:-
data = request.form
print json.loads(str(data.get('data'))) # throws an error
Upon printing data.get('data'), I get {applist:{ads:{ad:[{adsid:1,view_points:25,view_type:full,comment:Success}]}}} which is incorrect json, since double quotes("") are missing. How do I json load it?
The issue is with your original post request via curl. You are surrounding the post data with double quotes, but also using double quotes in the post body. Easiest fix is to surround the post body with single quotes:
curl --data 'data={"applist":{"ads":{"ad":[{"adsid":1,"view_points":25,"view_type":"full","comment":"Success"}]}}}' POSTURL
First of all, if you are using Flask, you should use request.json to get the already parsed json. To do so, you need to set the content type in your curl request:
-H "content-type: application/json"
Second, your data is not valid json. Use this one instead:
--data='{"applist":{"ads":{"ad":[{"adsid":1,"view_points":25,"view_type":"full","comment":"Success"}]}}}'

Categories

Resources