I am getting http code 400 (bad request) when I am trying to post a file to server using python requests library.
Corresponding curl request which is successful:
curl -X POST -i https://de.api.labs.sophos.com/analysis/file/static/v1 \
-H 'Authorization: auth_string' \
-H 'Content-Type: multipart/form-data' \
-F "file=@filename"
API documentation: https://api.labs.sophos.com/doc/analysis/file/static.html
Can someone help me out what I might be doing wrong?
My code so far:
import requests
url = "https://de.api.labs.sophos.com/analysis/file/static/v1"
headers = {'content-type': 'multipart/form-data', 'Authorization': authorization}
with open(filepath, 'rb') as f:
files = {'file': f} # Even tried {'file': f.read()}
r = requests.post(url, files=files, headers=headers)
if r.status_code in [200, 202]:
return r.json()
else:
return r
Try to do it this way:
import requests
url = "https://de.api.labs.sophos.com/analysis/file/static/v1"
headers = {'Authorization': authorization} # no Content-Type here
r = requests.post(url, headers=headers, files={"file": open(filepath, "rb")})
print(r.status_code, r.text)
You shouldn't set Content-Type header manually when posting files with requests.
There are 2 reasons why:
requests will set Content-Type to multipart/form-data implicitly before making an actual HTTP request (as it does for Content-Length for example)Content-Type: multipart/form-data you should specify a boundary as well. If no boundary is set, server will not be able to read data from request body correctly. So boundary is a required part of Content-Type header, if you use multipart/form-data.In your example you haven't set boundary for the request. The fact is that requests does not set it for you if you override Content-Type header (which you do). And then server is not able to read your file in request body. Therefore, it returns you 400 Bad Request.
You can check it by typing print(r.request.headers["Content-Type"]) after you've made your request. It will output this:
multipart/form-data
, but it must look like this instead:
multipart/form-data; boundary=6387a52fb4d1465310a2b63b2d1c6e70
On the other hand, curl adds boundary implicitly, so you everything is fine and you receive 200 OK.
You can check it as well:
curl -H 'Content-Type: multipart/form-data' -F "[email protected]" -v http://httpbin.org/post
Which outputs:
* Connected to httpbin.org (34.230.136.58) port 80 (#0)
> POST /post HTTP/1.1
> Host: httpbin.org
> User-Agent: curl/7.47.0
> Content-Type: multipart/form-data; boundary=------------------------d257f5f4377a3997
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With