How to curl in Python with header, data? - python

I'm trying replace the following curl command by a Python script:
curl --request POST \
--url https://xx.com/login \
--header 'Content-Type: application/json' \
--data '{
"email": "user#domain.com",
"password": "PASSWORD"
}'
Script that I tried:
import urllib.request
import json
body = {"email": "xxx#xx.com","password": "xxx"}
myurl = "https://xx.com/login"
req = urllib.request.Request(myurl)
req.add_header('Content-Type', 'application/json; charset=utf-8')
jsondata = json.dumps(body)
jsondataasbytes = jsondata.encode('utf-8') # needs to be bytes
req.add_header('Content-Length', len(jsondataasbytes))
response = urllib.request.urlopen(req, jsondataasbytes)
When I tried to run this script, it doesn't return me anything and show processed completed. Is my code logic correct? Or there is something wrong with my code?

For HTTP and HTTPS URLs, urllib.request.urlopen function returns a http.client.HTTPResponse object. It has different attributes and methods you can use,
For example,
HTTPResponse.read([amt]) - Reads and returns the response body, or up to the next amt bytes.
HTTPResponse.getheaders() - Return a list of (header, value) tuples.
HTTPResponse.status - Status code returned by server.
So in your case you could do check the status using status attribute . If it's successful read the response body using read method.
status_code = response.status
if status_code == 200: # request succeeded
response_body = response.read() # This will be byte object
response_body_as_string = response_body.decode('utf-8')

you can simply just use requests:
import requests
headers = {
'Content-Type': 'application/json',
}
data = '{\n"email": "user#domain.com",\n"password": "PASSWORD"\n}'
response = requests.post('https://xx.com/login', headers=headers, data=data)

Related

Failed to read the request form. Missing content-type boundary after convert request from curl or postman during send zip file

I would like to send a zip file using Python Requests. How to correct my code to send the zip file correctly?
My Curl request working fine and returns 200
curl -X 'POST' \
'https://xxx/bulk' \
-H 'accept: application/json;odata.metadata=minimal;odata.streaming=true'
-H 'Authorization: Basic xxx'
-H 'Content-Type: multipart/form-data'
-F 'File=#/home/dominik/ok/batch.zip;type=application/x-zip-compressed'
My Postman request returns 200. But the Python code from the Postman generator doesn't work.
Python code
headers = {
'accept': 'application/json;odata.metadata=minimal;odata.streaming=true',
'Content-Type': 'multipart/form-data',
'Authorization' : 'Basic xxx'}
def send_zip(zip_path, url, headers):
start_time = time.perf_counter()
zip_to_send = {'file': ('batch.zip', open(zip_path, 'rb'), 'application/x-zip-compressed')}
response = requests.request('POST', url, headers=headers, files=zip_to_send)
print(response.text, response.status_code)
end_time = time.perf_counter()
total_time = end_time - start_time
print(f'Total time to send zip: {total_time}')
my code returns
Failed to read the request form. Missing content-type boundary
I know about curlconverter but it returns the code with the file error
headers = {'accept': 'application/json;odata.metadata=minimal;odata.streaming=true',
'Authorization': 'Basic xxx,
# requests won't add a boundary if this header is set when you pass files=
# 'Content-Type': 'multipart/form-data',
}
fils = {'File': open('/hoome/ok/batch.zip;type=application/x-zip-compressed', 'rb'),}
response = requests.post('https://xxx/bulk', headers=headers, files=files, )

cURL, API in Python

I'm trying to code the following cURL API request in Python:
curl -X POST 'https://api.livecoinwatch.com/coins/list' \
-H 'content-type: application/json' \
-H 'x-api-key: <YOUR_API_KEY>' \
-d '{"currency":"USD","sort":"rank","order":"ascending","offset":0,"limit":2,"meta":false}'
I tried solving it with guidance of another post, like this:
headers = {
'x-api-key': <YOUR_API_KEY>,
'content-type': 'application/json',
'host': https://api.livecoinwatch.com/coins/list
}
url = https://api.livecoinwatch.com/coins/list
data = '{"currency": "USD","sort": "rank","order": "ascending","offset": 0,"limit": 50,"meta": true}'
response = requests.post(url, data=json.dumps(data), headers=headers)
print (response)
Unfortunately I get a "bad request" error.
Can someone please help me where I go wrong?
Assuming you have your urls wrapped in quotes, you should try giving to the data function parameter a dictionary instead of a string as the requests documentation says: data – (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request.
response = requests.post(url, data=json.loads(data), headers=headers)

Python requests doesn't upload file

I am trying to reproduce this curl command with Python requests:
curl -X POST -H 'Content-Type: application/gpx+xml' -H 'Accept: application/json' --data-binary #test.gpx "http://test.roadmatching.com/rest/mapmatch/?app_id=my_id&app_key=my_key" -o output.json
The request with curl works fine. Now I try it with Python:
import requests
file = {'test.gpx': open('test.gpx', 'rb')}
payload = {'app_id': 'my_id', 'app_key': 'my_key'}
headers = {'Content-Type':'application/gpx+xml', 'Accept':'application/json'}
r = requests.post("https://test.roadmatching.com/rest/mapmatch/", files=file, headers=headers, params=payload)
And I get the error:
<Response [400]>
{u'messages': [], u'error': u'Invalid GPX format'}
What am I doing wrong? Do I have to specify data-binary somewhere?
The API is documented here: https://mapmatching.3scale.net/mmswag
Curl uploads the file as the POST body itself, but you are asking requests to encode it to a multipart/form-data body. Don't use files here, pass in the file object as the data argument:
import requests
file = open('test.gpx', 'rb')
payload = {'app_id': 'my_id', 'app_key': 'my_key'}
headers = {'Content-Type':'application/gpx+xml', 'Accept':'application/json'}
r = requests.post(
"https://test.roadmatching.com/rest/mapmatch/",
data=file, headers=headers, params=payload)
If you use the file in a with statement it'll be closed for you after uploading:
payload = {'app_id': 'my_id', 'app_key': 'my_key'}
headers = {'Content-Type':'application/gpx+xml', 'Accept':'application/json'}
with open('test.gpx', 'rb') as file:
r = requests.post(
"https://test.roadmatching.com/rest/mapmatch/",
data=file, headers=headers, params=payload)
From the curl documentation for --data-binary:
(HTTP) This posts data exactly as specified with no extra processing whatsoever.
If you start the data with the letter #, the rest should be a filename. Data is posted in a similar manner as --data-ascii does, except that newlines and carriage returns are preserved and conversions are never done.

how to make post request in python

Here is the curl command:
curl -H "X-API-TOKEN: <API-TOKEN>" 'http://foo.com/foo/bar' --data #
let me explain what goes into data
POST /foo/bar
Input (request JSON body)
Name Type
title string
body string
So, based on this.. I figured:
curl -H "X-API-TOKEN: " 'http://foo.com/foo/bar' --data '{"title":"foobar","body": "This body has both "double" and 'single' quotes"}'
Unfortunately, I am not able to figure that out as well (like curl from cli)
Though I would like to use python to send this request.
How do i do this?
With the standard Python httplib and urllib libraries you can do
import httplib, urllib
headers = {'X-API-TOKEN': 'your_token_here'}
payload = "'title'='value1'&'name'='value2'"
conn = httplib.HTTPConnection("heise.de")
conn.request("POST", "", payload, headers)
response = conn.getresponse()
print response
or if you want to use the nice HTTP library called "Requests".
import requests
headers = {'X-API-TOKEN': 'your_token_here'}
payload = {'title': 'value1', 'name': 'value2'}
r = requests.post("http://foo.com/foo/bar", data=payload, headers=headers)

Python: Bad request in POST using requests

I am supposed to send this:
curl --header "Content-Type: text/plain" --request POST --data "ON" example.com/rest/items/z12
Instead, I am sending this:
import requests
headers = {"Content-Type": "text/plain"}
url = 'http://example.com/rest/items/z12'
_dict = {"ON": ""}
res = requests.post(url, auth=('demo', 'demo'), params=_dict, headers=headers)
And I am getting an Error 400 (Bad Request?)
What am I doing wrong?
The POST body is set to ON; use the data argument:
import requests
headers = {"Content-Type": "text/plain"}
url = 'http://example.com/rest/items/z12'
res = requests.post(url, auth=('demo', 'demo'), data="ON", headers=headers)
The params argument is used for URL query parameters, and by using a dictionary you asked requests to encode that to a form encoding; so ?ON= is added to the URL.
See the curl manpage:
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button.
and the requests API:
data – (optional) Dictionary, bytes, or file-like object to send in the body of the Request.
params parameter in the requests.post method is used to add GET parameters to the URL. So you are doing something like this :
curl --header "Content-Type: text/plain" --request POST example.com/rest/items/z12?ON=
You should instead use the data parameter.
import requests
headers = {"Content-Type": "text/plain"}
url = 'http://example.com/rest/items/z12'
res = requests.post(url, auth=('demo', 'demo'), data="ON", headers=headers)
Moreover, if you give a dictionnary to the data parameter, it will send the payload as "application/x-www-form-urlencoded". In your curl command, you send raw string as payload. That's why I changed a bit your example.

Categories