How to send integer in POST to Tornado's AsyncHTTPTestCase.fetch()? - python

I'm using python's Tornado framework to test my HTTP POST endpoint. To do this, I'm using the fetch method.
data = urllib.urlencode({
'integer_arg': 1,
'string_arg': 'hello'
})
resp = AsyncHTTPTestCase.fetch('/endpoint',
method='POST',
headers={'h1': 'H1',
'h2': 'H2',
'Content-Type': 'application/json'},
body=data)
When I do this, the endpoint receives integer_arg as the string "1" even though I want it to receive it as an integer. This is understandable because urllib.urlencode converts it to a string. So how can I ensure it receives an integer?
Just eliminating the call to urllib.urlencode doesn't work.
By the way, when I hit the same endpoint with a naked curl call as shown below, the endpoint properly receives integer_arg as the integer 1.
curl \
--request POST \
--header "h1: H1" \
--header "h2: H2" \
--header "Content-Type: application/json" \
--data '{
"integer_arg": 1,
"string_arg": "hello"
}' \
"http://localhost:8000/endpoint"

The body in curl is significantly different than that in AsyncHTTPClient.fetch. With python you urlencode the data in curl there is just json. So simply change urlencode with json.dumps:
import json
from tornado.ioloop import IOLoop
from tornado.httpclient import AsyncHTTPClient
from tornado.gen import coroutine
#coroutine
def main():
client = AsyncHTTPClient()
body = json.dumps({
'integer_arg': 1,
'string_arg': 'hello'
})
yield client.fetch(
'/endpoint', method='POST', body=body,
headers={'h1': 'H1', 'h2': 'H2', 'Content-Type': 'application/json'}
)
ioloop = IOLoop.instance()
ioloop.run_sync(main)

Related

Sending json requests to flask server in pytest

I want to send a json with a POST request, to a specific endpoint to my server, in pytest.
This is what i normally feed the server with curl:
curl --header "Content-Type: application/json" --request POST --data '{"item":"ZycugK6yXdHgf8foQTUnKY.txt","method":"one"}' 0.0.0.0:5000/convert
And this is how i tried to recreate it in pytest:
data = {"item": filename, "method": method}
response = client.post('/convert', content_type='application/json', data=data)
Where the filename, and method parameters are received as inputs to the function (forwarded by a decorator).
However, i keep getting a 400 - Bad Request, which means that i am doing something wrong with my request.
I think this will work:
data = {"item": filename, "method": method}
response = client.post('/convert', content_type='application/json', data=json.dumps(data))
You need to serialize the data.
It depends on the client you are using.
For requests, you could use simply
response = client.post("/convert", json=data)

How to pass a list to data parameter in requests.patch?

I'm trying to add a role to a user in Auth0 via requests in python, but I'm having problems with the data part. I've tried to send this data passing a pure list, using json parameter instead of data and other options...
requests.patch(
url='my_url',
data=json.dumps(["my_role_id"]),
headers={'Authorization': 'Bearer my_token',
'Content-Type': 'application/json'}
)
Following the docs, if I try to send the same data via cURL or in a client like Insomnia, it works.
curl --request PATCH \
--url 'https://{extension_url}/users/{user_id}/roles' \
--header 'Authorization: Bearer {access_token}' \
--header 'Content-Type: application/json' \
--data '[ "{role_id}" ]'
The data content passed to service in the python sample is not the same as in the cURL sample. Try this (postman-echo helps to figure out what is going on):
import requests
import json
role_ids = ["my-role-id"]
role_id_array = [ "{%s}" % x for x in role_ids ]
resp = requests.patch(
url='http://postman-echo.com/patch',
data=json.dumps(role_id_array),
headers={'Authorization': 'Bearer my_token',
'Content-Type': 'application/json'}
)
print(resp.content)
I solved it! My url was wrong with the user_id incomplete and Auth0's authorization API didn't tell me that.

change curl cmd to python

I am a beginner. I am trying to change a curl cmd to an actually Post request in my python code.
Each time, I am getting either a 404 or 400 errors. I am a bit lost. Thanks.
Curl request : (echo -n '{"data": "'; base64 test-1.pdf; echo '", "extension": ".pdf"}') | curl -X POST -H "Content-Type: application/json" -d #- http://localhost:5000
My python code:
import json
import requests
url ='http://localhost:5000/POST'
newHeaders = {'Content-Type': 'application/json'}
response = requests.post(url, json={"data": "'; base64 test-1.pdf; echo '", "extension": ".pdf"},headers=newHeaders)
print("Status code: ", response.status_code)
response_Json = response.json()
print("Printing Post JSON data")
print(response_Json['data'])
print("Content-Type is ", response_Json['headers']['Content-Type'])
Your URL is wrong and should not have the /POST at the end, but in addition to that, you need to actually base64-encode the test-1.pdf (this is what the shell command that runs curl is doing).
You could use this (combined with the code in the question) to put the correct value into the parameters dictionary.
import base64
#...
b64 = base64.b64encode(open("test-1.pdf", "rb").read()).decode()
response = requests.post(url,
json={"data": b64,
"extension": ".pdf"},
headers=newHeaders)

Issues with JSON Data in Python

I am working on a project to incorporate Verizon Thingspace REST APIs into a Python program.
A co-worker provided me with an example in CURL that works (I am not familiar with Curl so am trying to convert into Python).
curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" --header "VZ-M2M-Token: 621d9779-f8bc-4fe9-91dd-b726c52e7117" --header "Authorization: Bearer 89ba225e1438e95bd05c3cc288d3591" -d "{\"accountName\": \"TestAccount-1\"}" https://thingspace.verizon.com/api/m2m/v1/devices/actions/list
I'm trying to convert this exact same request into a Python function. Here's what I have:
import requests
def getList(token):
url = "https://thingspace.verizon.com/api/m2m/v1/devices/actions/list"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer 89ba225e1438e95bd05c3cc288d3591",
"VZ-M2M-Token": "f7ef3a35-abb6-418b-92d4-7cdac8b06c5f",
}
data = {"accountName": "TestAccount-1"}
print data
deviceList = requests.post(url, data=data, headers=headers)
print headers
print (deviceList.status_code, deviceList.reason, deviceList.text)
return deviceList
When I run this, I get the following error message back in JSON:
(400, 'Bad Request',
u'{"errorCode":"REQUEST_FAILED.UnexpectedError","errorMessage":"Could
not read document: Unrecognized token \'accountName\': was expecting
(\'true\', \'false\' or \'null\')\n at [Source:
java.io.PushbackInputStream#51ceaf1d; line: 1, column: 13]; nested
exception is com.fasterxml.jackson.core.JsonParseException:
Unrecognized token \'accountName\': was expecting (\'true\', \'false\'
or \'null\')\n at [Source: java.io.PushbackInputStream#51ceaf1d;
line: 1, column: 13]"}')
You can reference the API information here: https://thingspace.verizon.com/developer/apis#/Connectivity%20Management/API%20Reference/Retrieve%20Device%20Information.html
I believe there might be something wrong with my JSON string but I need another set of eyes.
data is not automatically converted to json, you have to do this explicitly:
deviceList = requests.post(url, data=json.dumps(data), headers=headers)

RESTFUL POST with Python request to Glassfish Server

I'm having a difficulty trying to make a Python REST POST to a webservice running on Glassfish. I have verified that POST works ok using CURL but having no luck with Python.
Here is the CURL request that works ok.
curl -X POST -H "Content-Type: application/json" -d '{"id":1,"lastname":"smith"}'
http://192.168.0.20:8080/field1/resources/com.field1entity.field1
Here is the Python code to make the POST request
import urllib
import httplib2
def call():
http = httplib2.Http()
url = 'http://192.168.0.20:8080/field1/resources/com.field1entity.field1'
params = urllib.urlencode({"id":11111,"lastname":"oojamalip"})
response, content = http.request(url, 'POST', params, headers={'Content-type':'application/json'})
print "lets stop here to have a looksy at the variables"
print content
if __name__ == '__main__':
namesPage = call()
print namesPage
Output from console,
Unexpected character ('l' (code 108)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: org.apache.catalina.connector.CoyoteInputStream#18f494d; line: 1, column: 2]
Hope someone can shed some light on the problem.
thanks
Nick
You are url encoding the prams and then telling the server it is json encoded
import json
params = json.dumps({"id":11111,"lastname":"oojamalip"})
# then
response, content = http.request(url, 'POST', body=params, headers={'Content-type':'application/json'})

Categories