Sending json requests to flask server in pytest - python

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)

Related

curl POST works in command line but not with Python

I need to run a curl POST to obtain API token as following:
curl - i -v -k -X POST -d '{"authType":"LOCAL","password":"mypw","username":"admin"}' --header "Content-Type:application/json" "https://x.x.x.x:xxxx/myapi_auth_path/login"
Everything runs well and I can obtain the token.
Now I want to do that with Python requests:
import requests
address = "https://x.x.x.x:xxxx/myapi_auth_path/login"
headers = {"Content-Type": "application/json"}
data = {"authType": "LOCAL",
"password": "mypw",
"username": "admin"}
res = requests.post(address, data=data, headers=headers, verify=False)
I get this error:
Expecting value: line 1 column 1 (char 0)
What is wrong with the Python code?
You're using data=data which means your data dict will be form-encoded.
You can use json=data instead (this will also set the Content-Type header for you)
It's covered in this section of the docs,

Passing a remote file to a http post request in python

I have a rest api that offers an upload file post functionality. To test this, I simply did this on my python test code:
fo = open('file.zip', 'rb')
rb_file = {'confile': ('file.zip', fo, 'multipart/form-data')}
resp = requests.post(url,files=rb_file)
fo.close()
This request returns a uuid response {ce9f2d23-8ecd-4c60-9d31-aef0be103d44} that is needed for initiating another post run for a scan.
From Swagger, manually passing this uuid to the scan post request generates the following curl:
curl -X POST "http://....../scan" -H "Content-Type: multipart/form-data" -F "FilID=ce9f2d23-8ecd-4c60-9d31-aef0be103d44"
My question is how to convert this curl to a python request code noting that I no longer have the file on my local machine. The server seems to be expecting a -F rather than a param. How do I pass a file that doesn't exist on my local machine to http request in this case? All I have is the filID. I tried running as param but that doesn't find the resource.
try this !
import requests
headers = {
'Content-Type': 'multipart/form-data',
}
files = {
'FilID': (None, 'ce9f2d23-8ecd-4c60-9d31-aef0be103d44'),
}
response = requests.post('http://....../scan', headers=headers, files=files)

translating simple curl call to python/django request

I'm attempting to translate the following curl request to something that will run in django.
curl -X POST https://api.lemlist.com/api/hooks --data '{"targetUrl":"https://example.com/lemlist-hook"}' --header "Content-Type: application/json" --user ":1234567980abcedf"
I've run this in git bash and it returns the expected response.
What I have in my django project is the following:
apikey = '1234567980abcedf'
hookurl = 'https://example.com/lemlist-hook'
data = '{"targetUrl":hookurl}'
headers = {'Content-Type': 'application/json'}
response = requests.post(f'https://api.lemlist.com/api/hooks/', data=data, headers=headers, auth=('', apikey))
Running this python code returns this as a json response
{}
Any thoughts on where there might be a problem in my code?
Thanks!
Adding to what nikoola said, I think you want that whole data line to be as follows so you aren't passing that whole thing as a string. Requests will handle serializing and converting python objects to json for you [EDIT: if you use the json argument instead of data].
source: https://requests.readthedocs.io/en/master/user/quickstart/#more-complicated-post-requests
Instead of encoding the dict yourself, you can also pass it directly
using the json parameter (added in version 2.4.2) and it will be
encoded automatically:
Note, the json parameter is ignored if either data or files is passed.
Using the json parameter in the request will change the Content-Type
in the header to application/json.
data = {"targetUrl":hookurl}
import requests
headers = {
'Content-Type': 'application/json',
}
data = '{"targetUrl":"https://example.com/lemlist-hook"}'
response = requests.post('https://api.lemlist.com/api/hooks', headers=headers, data=data, auth=('', '1234567980abcedf'))
You can visit this url:-
https://curl.trillworks.com/

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