How to send file using Request Python with some headers? - python

I tried to send file with some headers like:
files = {'file': (file, open(file, 'rb'), {'Content-type': 'multipart/form-data; boundary=---BOUNDARY', 'Authorization' : 'Basic ' + api_key})}
r = requests.post(base_url, files=files)
Server returned 401 error that means absent header Authorization. But I sent it

For Basic Authentication you can follow the requests docs. It's visible on the very first line of code in the example on that page.
Use the auth keyword argument to supply a 2-tuple of username and password:
response = requests.post(base_url, files=files, auth=('username', 'password'))
Edit:
If you want to send actual headers, rather than things like Basic Auth, you can do that with the headers keyword argument. This allows you to give a dict of headers you would like to send. For example:
headers = {'Content-Type': 'application/json'}\
response = requests.post(url, data=data, headers=headers)
The auth argument, should be a simplification of the above because Basic Auth is so common, but don't quote me on that one.

You can follow this example to take it from the official documentation I think you should try it first in postman, with the json then and do it from python.
This information is taken from the official documentation
python

Related

Request API POST

I'm having a problem with a Python request, where I pass the body url to the API data.
Note: I have a Node.js project with TypeScript that works normally, prints to the screen and returns values. However if I try to make a request in Python it doesn't work with an error 401.
Below is an example of how the request is made in Python. can you help me?
import requests
url = 'https://admins.exemple'
bodyData = {
'login': 'admins',
'pass': 'admin',
'id': '26' }
headers = {'Content-Type': 'application/json'}
resp = requests.post(url, headers=headers, data=bodyData)
data = resp.status_code
print(data)
Please dump a dict to a json string as follows:
import json
resp = requests.post(url, headers=headers, data=json.dumps(bodyData))
You also can pass your dict to json kwarg
resp = requests.post(url, headers=headers, json=bodyData)
It will set Content-Type: application/json and dump dict to json automatically
You are not correctly authenticating with the server. Usually, you need to send the username and password to a "sign in" route which will then return a token. Then you pass the token with other requests to get authorization. Since I don't know any details about your server and API, I can't provide any more details to help you out.

Alfresco basic authentication works with curl but not with python

I am having a problem with authentication error from Alfresco, maybe somebody could enlighten me while im trying to find log files from the mess that is Alfresco.
curl -uadmin:password -X POST https://hostname/alfresco/api/-default-/public/alfresco/versions/1/nodes/node_uuid/children -F filedata=#/home/user/file.pdf
Now when I am trying to use python requests(TM) it gives me a 401. Ive checked the requests and they both send the same Authentication hash
This is the python code:
def handle_row_for_request(row):
url = 'https://' + hostname + '/alfresco/api/-default-/public/alfresco/versions/1/nodes/' + base_uuid + '/children'
data = '/home/user/file.pdf'
with open(data, 'rb') as payload:
headers={"content-type": "multipart/form-data"}
response = requests.post(url, headers=headers, data=payload, auth=(username, password))
You are using the data argument, but you need to use the file argument:
def handle_row_for_request(row):
url = 'https://' + hostname + '/alfresco/api/-default-/public/alfresco/versions/1/nodes/' + base_uuid + '/children'
files = {'filedata': ('/home/user/file.pdf', open('/home/user/file.pdf', 'rb'))}
headers={"content-type": "multipart/form-data"}
response = requests.post(url, headers=headers, files=files, auth=(username, password))
Below is the Python code which works fine for the upload which also uses the basic auth. Please check the request params.
import json
import requests
url = "http://localhost:8080/alfresco/service/api/upload"
auth = ("admin", "admin")
files = {"filedata": open("/tmp/foo.txt", "rb")}
data = {"siteid": "test", "containerid": "documentLibrary"}
r = requests.post(url, files=files, data=data, auth=auth)
print(r.status_code)
print(json.loads(r.text))
There were 2 parts to the problem. First I needed to use the file argument instead of data. On top of that Alfresto wants to get 'filedata' string inside the file argument.
Secondly auth(user,pw) generated a hash that had a single = sign in the end and alfresco said 401. When I used cURL and got the password hash from there it had two = signs in the end. Weird right? But that worked. Instead of using auth(user,pw) I set the 'Authorization': 'Basic ${base64thing}' as the authentication.
response = requests.post(url, headers={'Authorization': 'Basic base64string'}, files={'filedata': open(/path/, 'rb')})```

How to troubleshoot a Python Requests POST failure when the same POST is working fine in Postman?

I continue to get a very generic, unhelpful error message from python requests when making a POST request that works fine in Postman.
No matter what I try, I continue to receive one of two error messages. And note that the calling python script does not have a line 155, nor does the payload contain the letter "u":
{"error":{"detail":"SyntaxError: Unexpected token: u (sys_script_include.d2426c9ec0a8016501958bf2ac79c775.script; line 155)","message":"Unexpected token: u"},"status":"failure"}
{"error":{"message":"Unexpected token: u","detail":"SyntaxError: Unexpected token: u (sys_script_include.d2426c9ec0a8016501958bf2ac79c775.script; line 155)"},"status":"failure"}
In Postman, the parameters are correctly interpreted and then appended to the url such as:
https://areallylongurl?params={"catalogItem": "Req Name"}
In Python Requests I have tried various combinations of things without luck.
payload = {"params": '{"catalogItem": "Req Name"}'}
response = requests.post(url, headers=headers, json=payload, verify=False)
response = requests.post(url, headers=headers, json=json.dumps(payload), verify=False)
response = requests.post(url, headers=headers, data=payload, verify=False)
response = requests.post(url, headers=headers, data=json.dumps(payload), verify=False)
By using this very helpful SO answer, I was able to further analyze how the Requests library interpreted my provided payload but I am still not sure exactly how to interpret this generic error message, or what the cause may be.
Does anyone have thoughts as to what the underlying issue could be? And note that I can GET from this API without issue from Requests, it's only the POST that's problematic.
Since in postman the parameters are "appended to the url" like https://areallylongurl?params={"catalogItem": "Req Name"}, it means that the request is likely a GET request with JSON passed as a value to the params parameter, rather than a payload to a POST request, in which case you should do this instead:
response = requests.get(url, headers=headers, params={"params": json.dumps(payload)}, verify=False)

Python HTTP Post with upload file and headers generated from Postman

I'm using Python 2.7.
I want to make a HTTP POST using requests, where I upload a file and a key that must go in the HTTP Headers.
For that I've used the application Postman, where it works really fine.
On Postman I've added only the necessary header, which is a Authorization with some key.
On the body, Ive choosen form-data and then the key is an input_image, and they the image itself.
Now I want to replicate this into Python2.7, so I've chose to see the Python code on Postman, which was this one:
import requests
url = "https://foo.com/bar/stuff"
payload = "------WebKitFormBoundary7MA4YDxkTrZu1gW\r\nContent-Disposition: form-data; name=\"input_image\"; filename=\"C:\\Test\\projs\\Supermarket\\doritos.jpeg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YDxkTrZu1gW--"
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YDxkTrZu1gW",
'Authorization': "myAuthorizationKey",
'Cache-Control': "no-cache",
'Postman-Token': "0efwd6e8-051c-4ed5-8d6f-7b1bd135f4d5"
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
This simply doesn't work. It has the same behaviour as if I didn't send any image using Postman. It looks like the payload string is not being send correctly.
Question:
What is wrong with this Postman auto-generation code in order to send a HTTP POST with image upload and with header at the same time in Python?
I think Postman is doing some logic we are not really aware of. But the package requests provide a way to upload images.
files = {'media': open('my_image.jpg', 'rb')}
r = requests.post(url, files=files, headers=hearders)
According to the server you are sending the image to, the parameters name, this code might need to be slightly changed.
the only trick works here is your code should be same as you post request in postman, no extra headers need to be added , your post request should look like the same as it is in postman.
I could do this by changing my file to an image file and then posting it in my post request.
with open('grass-small.png', 'rb') as imageFile:
imageStr = base64.urlsafe_b64encode(imageFile.read())
files = {'document': ('grass-small.png', imageStr ), 'document_type':(None,'grass')}
This worked for me
import requests
url = 'http://iizuka.cs.tsukuba.ac.jp/projects/colorization/web/'
files = {'file': ("my_img_path/myImage.jpeg", open('my_img_path/myImage.jpeg', 'rb'),'image/jpg')}
r = requests.post(url, files=files)

Python mulitpart/formdata POST request within Zapier Code

I'm currently working with Zapier to automate some tasks but I got stuck on the following :
I'm trying to send a POST request using the Zapier Webhooks containing a file. I could make it work trough postman as the API of Debitoor (that's where I am sending to) is pretty clear.
However, I can not make it work within Zapier Webhooks. I also tried to use Zapier Code (Python) as I can view the python code from the postman. But I am not familiar with that and might need some help to get it started.
1.) First of all, this is the API reference: https://developers.debitoor.com/api-reference#files
2.) I then used Postman with this code (Python requests)which was working :
import requests
url = "https://api.debitoor.com/api/files/v1"
querystring = {"token":"eyJ1c2VyIjoiNWE0NmVjYjUxOTE0ODEwMDFjMTkxYzZmIiwiYXBwIjoiNTdiMmZlMDkxZTkwMjQwZjAwNDZhNWEyIiwiY2hhbGxlbmdlIjowLCIkZSI6MCwiJHQiOjE1MjE4NzAwNTQ1OTd9CsKRw5xbw5_DhHUWw5QJw4zDj8KnXsOaeMKA","fileName":"test.pdf"}
payload = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"file\"; filename=\"Bildschirmfoto 2018-04-05 um 09.59.46 1.png\"\r\nContent-Type: image/png\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--"
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'cache-control': "no-cache",
'postman-token': "716e7723-2dc1-6384-059d-960feb563443"
}
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
print(response.text)
3.) Tried to copy the code to Zapier Code, but I don't know how to implement the file. In Zapier I am triggering an inbound email to grab the attachment, which is then "hydrated". It looks like this :
hydrate|||.eJwtjMsOwiAUBf_lrosKNFDZu3Xh1hjC46KklTaFxDRN_11qXJ7JzFkhplxMcqijB8U5l7yT5wZCxMHrZN4Iqo4BMzTgXuh63eMCioruLKiobEwFU9FlmXb1WrX-Y-ZnBrX-Qj2NsSpzBfcV_o-3C2GUisPkwx7sj5D5UQpDmeMnwqW1pPWBE-OYJdYwdCJQT9sWtse2fQEK1Tjl:1eqY0S:s2Ek27XO54PVSm9q_mVMDN8o1uY|||hydrate
How do I connect the Python code to the hydrated file? I have no experience with files and could not find any useful help. Hope someone has an idea?
I was trying to import AWS S3 files to my API.
It turns out that Zapier hydrated my file just as described here.
Then I successfully extracted the content of my file and sent it to my API like this:
import urllib.request
auth_token = input_data['auth_token'] # Authentication token for my API
csv_file = input_data['csv_file'] # The "hydrate|||..." variable: that's my S3 file
file_type = 'text/csv'
fp = urllib.request.urlopen(csv_file)
file_bytes = fp.read() # Binary content of my S3 file
fp.close()
url = 'http://my.api.com/importer/resource'
headers = {
'accept': 'application/vnd.api-v1+json',
'authorization': auth_token,
'user-agent': 'Zapier'
}
files = {'csv_file': ('bulk_resources.csv', file_bytes, file_type, {'Expires': '0'})}
response = requests.post(url, headers=headers, files=files)
return response.json()

Categories