mapping a curl command to equal python requests function - python

Really would appreciate some help to understand what I'm missing.
I have a working curl command that I need to map to an equal python function using requests.
All my attempts end up failing with a message of :
requests.exceptions.ConnectionError: ('Connection aborted.', error(32, 'Broken pipe'))
The original curl command is:
curl -X POST "https://x.x.x.x/api/upload" -H "accept: application/json"
-H "authorization: Basic BlaBla" -H "Content-Type: multipart/form-data"
-F "file=#SomeFile.zip;type=application/zip"
My failing python code is:
def importZip(self, fAuth, infile, dir=''):
trgtURL = fAuth.url+"/api/upload"
headers = {'Content-Type': 'multipart/form-data'}
data = {'upload':''}
files = {'file': (infile, open(dir+infile,'rb'))}
r = fAuth.session.post(trgtURL, files=files, data=data)
fAuth is just a class I use to authenticate and retain the session for follow up calls. I can use the fAuth instance to do gets no problem, so I suspect the problem isn't tied to the underlying session.
Any ideas or insight are greatly appreciated.

-H "accept: application/json" -H "Content-Type: multipart/form-data" equal to {"Accept": "application/json"} in python. Content-Type is not necessary, because library will add it.
-H "authorization: Basic BlaBla" is a bit special in header. So you should read Authentication
So you job is to add auth param, and modify your headers by your command example.
def importZip(self, fAuth, infile, dir=''):
trgtURL = fAuth.url+"/api/upload"
headers = {"Accept": "application/json"}
files = {'file': (infile, open(dir+infile,'rb'), "application/zip")}
auth = (user,passwd)
r = fAuth.session.post(trgtURL, headers=headers, files=files, auth=auth)

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,

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)

Python3.6 requests.post results in ConnectionError number 104, but all is fine when using curl

I am trying to rewrite a curl command to python. The idea is the following: we upload an audio file, and get in return what it was said in it in text - e.g. speech to text.
The site has provided us a curl example, which makes a post request and in return receives a simple response.
When I tried to convert the curl request into python one (with little help from https://curl.trillworks.com/ ) I get ConnectionError number 104, connection reset by peer.
I strongly suspect that this happens because when I make the connection vie curl firstly I get the response: < HTTP/1.1 100 Continue, and after short time of waiting another response: < HTTP/1.1 200 OK, with the some sample data. I think that python requests.post just hangs at the first HTTP/1.1 100.
I could not handle or reset the connection using try... except..., neither succeeded in looping it with time.sleep().
Any ideas?
P.S. CODE:
Curl command:
curl "LINK TO SERVER" -H "Content-Type: audio/x-speex;rate=16000" -H "Accept-Language: ENUS" -H "Transfer-Encoding: chunked" -H "Accept: application/xml" -H "Accept-Topic: Dictation" -k --data-binary #audio_16k16bit.pcm
Python equivalent:
#!/bin/python
import requests
import time
headers = {
'Content-Type': 'audio/x-wav;codec=pcm;bit=16;rate=16000',
'Accept-Language': 'ENUS',
'Transfer-Encoding': 'chunked',
'Accept': 'application/xml',
'Accept-Topic': 'Dictation',
}
params = (
('appId', ''),
('appKey',''),
('id', ''),
)
data = open('audio_16k16bit.pcm', 'rb').read()
r = requests.post('LINK TO SERVER', headers=headers, data=data, verify=False)
print(r.content)
SOLUTION
Should remove and let the server determine the type of file, also since we are sending it as one file chunked is not needed:
'Content-Type': 'audio/x-wav;codec=pcm;bit=16;rate=16000',
'Transfer-Encoding': 'chunked'

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)

Categories