422 when posting file with requests - python

So I've been trying to figure this out all day but haven't been able to make any progress. I have this curl command, which works:
curl -X POST -H "x-hermes-key: <KEY>" -H "Accept: application/json" --form file='#example_files/ex1.pdf' <URL> -kv
When I try to run its equivalent in python with requests, I get a 422 error:
header = {
"Accept": "application/json",
"X-Hermes-Key": <KEY>
}
f = {'file': open("example_files/ex1.pdf", "rb")}
r_create = requests.post(url=<URL>, headers=header, files=f)
Can anyone help me see where I'm making a mistake?

The following should match the curl command and POST with content-type=multipart/form-data.
You can set the filename, content_type, and headers explicitly in a tuple for the 'file' value.
headers = {
"Accept": "application/json",
"X-Hermes-Key": <KEY>
}
url = <URL>
files = [('file', ('ex1.pdf', open('example_files/ex1.pdf', 'rb'),
'application/octet-stream'))]
r = requests.post(url=url, headers=headers, files=files)
print(r.status_code)

Related

Curl command works fine, while Python requests returns 404

Curl
curl "https://api.wanikani.com/v2/summary" \ -H "Wanikani-Revision: 20170710" \ -H "Authorization: Bearer <API-KEY>"
This command returns the expected json.
Python code
import requests
headers = {"Wanikani-Revision": "20170710", "Authorization": "Bearer <API-KEY>"}
res = requests.post('https://api.wanikani.com/v2/summary', headers = headers)
print(res.text)
This code returs 404.
{"error":"Not found","code":404}
That function only accepts GET. Look https://docs.api.wanikani.com/20170710/#summary
Try:
import requests
headers = {"Wanikani-Revision": "20170710", "Authorization": "Bearer <API-KEY>"}
res = requests.get('https://api.wanikani.com/v2/summary', headers = headers)
print(res.text)

How to Run this API Request Using Python

I am very new to python and API Integration. Can anyone pls tell me how do I run this okta document using python?
curl -v -X GET
-H "Accept: application/json"
-H "Content-Type: application/json"
-H "Authorization: SSWS ${api_token}"
"https://${yourOktaDomain}/api/v1/apps"
You can use urllib for do it.
Example:
from urllib.request import Request, urlopen
api_token = "..."
yourOktaDomain = "..."
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Autorization": "SSWS " + api_token
}
request = Request("https://" + yourOktaDomain + "/api/v1/apps", headers=headers)
response = urlopen(request)
data = response.read()
import requests
import json
yourOktaDomain = 'something.okta.com'
api_token= ''
payload = ""
headers = {
'Accept': "application/json",
'Content-Type': "application/json",
'Authorization': "SSWS "+api_token
}
response1=requests.request("GET", 'https://'+{yourOktaDomain}+'/api/v1/apps', data=payload, headers=headers)
response1.json()

How to send files via post request in python similar to curl? (W3C validator)

I am trying to send a local html file from my computer to the https://validator.nu/ from W3C to validate it.
I found this curl command which worked perfectly fine in terminal:
curl -H "Content-Type: text/html; charset=utf-8" \
--data-binary #FILE.html \
https://validator.w3.org/nu/?out=gnu
But how to do a post request in python equivalent to the mentioned curl command?
I have already tried the following but it did not work correctly.
headers = {
'Content-Type': 'text/html',
'charset': 'utf-8',
}
url = "https://validator.w3.org/nu/?out=gnu"
files = {'upload_file': open('filename.html','rb')}
r = requests.post(url, files=files, data=data, headers=headers)
print(r.text)
Can someone please help me in doing a request in python?
You need to send the content of the file as binary data:
import requests
headers = {
'Content-Type': 'text/html',
'charset': 'utf-8',
}
url = "https://validator.w3.org/nu/?out=gnu"
with open("filename.html", "rb") as f:
data = f.read()
r = requests.post(url, data=data, headers=headers)
print(r.text)

How should this PUT curl be converted to python requests?

How can I convert this CURL PUT request to python requests:
The curl is
curl -X PUT "https://example.com" -H "accept: application/json" -H "Content-Type: application/json-patch+json" -d "{ \"userName\": \"exampleuser\", \"password\": \"examplepass\"}"
Currently got
headers = {"accept": "application/json",
"Content-Type": "application/json-patch+json"}
data = {'\"userName\"': '\"exampleuser\"',
'\"password\"': '\"examplepass\"'}
response = requests.put(url=url, data=data, headers=headers)
print(response)
Currently getting a 401 response. Unfortunately, the curl converter does not recognise it.
In bash, you escaped the quotes of the json
In Python, you shouldn't need to
data = {'userName' : 'exampleuser',
'password': 'examplepass'}
Then, you're sending json, so do json=data instead of data=data

How to verify outgoing HTTP request from python's module?

I need to write Python equivalent code for below mentioned working curl(I have replaced the credentials for obvious reason, but it gives back 200 status.).
curl -X POST \
'https://api.lever.co/v1/candidates?dedupe=true&perform_as=user_123' \
-H 'Authorization: Basic token_123' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: multipart/form-data' \
-H 'Postman-Token: 58cafa90-7ae4-47db-a144-4e9d430ffc94' \
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F 'files[]=#/Users/gaurav/lever_resume.pdf' \
-F 'emails[]=a#b.com'
So, I ended up in writing this snippet.
user_email = 'user#domain.com'
admin_id = '20f3975a-543f-4ca8-b215-2f851232a0ad'
client_id = '893728937298'
client_secret = '32032'
file_path = '/Users/ttn/Desktop/a.txt'
file_name = 'a.txt'
logging.basicConfig(level=logging.DEBUG)
url = "https://api.lever.co/v1/candidates"
files = {
'files[]': (file_name, open(file_path,'rb')),
}
auth = HTTPBasicAuth(client_id, client_secret)
querystring = {
"perform_as": admin_id,
"dedupe": 'true'
}
payload = {
'emails[]': user_email
}
headers = {
'Content-Type': "multipart/form-data",
"Cache-Control": "no-cache",
"content-type": "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
}
response = requests.post(url,
headers=headers,
params=querystring,
data=payload,
auth=auth,
files=files)
req = response.request
# print(curlify.to_curl(req))
print('\n==== Headers', req.headers)
print('\n==== Body', req.body)
print('\n==== form-data', str(req))
print(response.text)
Question
Since Python version of Curl is not working(giving 502 error instead of 200), so How can I compare the two? Can I generate the Curl out of Python's request`?
Can someone spot mistake in my Python version? I am suspecting some problem at form-data being passed (to collect evidence, I need answer to above question)
Edit
There seems to be a curlify package. But It looks like it does not support distinction between -d and -F parameters.
Try this:
import requests
headers = {
'Authorization': 'Basic token_123',
'Cache-Control': 'no-cache',
'Content-Type': 'multipart/form-data',
'Postman-Token': '58cafa90-7ae4-47db-a144-4e9d430ffc94',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW',
}
params = (
('dedupe', 'true'),
('perform_as', 'user_123'),
)
files = {
'files[]': ('/Users/gaurav/lever_resume.pdf', open('/Users/gaurav/lever_resume.pdf', 'rb')),
'emails[]': (None, 'a#b.com'),
}
response = requests.post('https://api.lever.co/v1/candidates', headers=headers, params=params, files=files)
#NB. Original query string below. It seems impossible to parse and
#reproduce query strings 100% accurately so the one below is given
#in case the reproduced version is not "correct".
# response = requests.post('https://api.lever.co/v1/candidates?dedupe=true&perform_as=user_123', headers=headers, files=files)oduced version is not "correct".
# response = requests.post('https://api.lever.co/v1/candidates?dedupe=true&perform_as=user_123', headers=headers, files=files)
Reference: https://curl.trillworks.com/#python

Categories

Resources