Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python requests - POST Multipart/form-data without filename in HTTP request

I am trying to replicate the following POST request using the requests module in python:

POST /example/asdfas HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: keep-alive Content-Type: multipart/form-data; boundary=---------------------------241652170216373 Content-Length: 279  -----------------------------241652170216373 Content-Disposition: form-data; name="value_1"  12345 -----------------------------241652170216373 Content-Disposition: form-data; name="value_2"  67890 -----------------------------241652170216373-- 

The documentation for requests suggests that the files argument should be used.

When I attempt the following call:

import requests requests.post('http://example.com/example/asdfas', files={'value_1': '12345',                                                            'value_2': '67890'}) 

I get the following HTTP request:

'Accept': '*/*',  'Accept-Encoding': 'gzip, deflate, compress',  'Content-Length': '264',  'User-Agent': 'python-requests/2.2.1 CPython/3.3.2 Windows/7',  'Content-Type': 'multipart/form-data; boundary=273f13699c02429db4eb95c97f757d38' --273f13699c02429db4eb95c97f757d38 Content-Disposition: form-data; name="value_1"; filename="value_1"  12345 --273f13699c02429db4eb95c97f757d38 Content-Disposition: form-data; name="value_2"; filename="value_2"  67890 --273f13699c02429db4eb95c97f757d38-- 

I have also tried to use the data argument:

import requests requests.post('http://example.com/example/asdfas', data={'value_1': '12345',                                                           'value_2': '67890'}) 

resulting in the following HTTP request:

'Content-Type': 'application/x-www-form-urlencoded',  'Content-Length': '27',  'User-Agent': 'python-requests/2.2.1 CPython/3.3.2 Windows/7',  'Accept': '*/*',  'Accept-Encoding': 'gzip, deflate, compress' value_2=67890&value_1=12345 

The issue I'm having is that using the files argument results in a call that the server doesn't recognize, presumably due to the unexpected "filename" information sent in the HTTP request. Using the data argument sends the wrong Content-Type header.

The first request is known to be working on the server I wish to send the request to - what is the correct function call to identically replicate the first HTTP request?

Edit: Sample HTML form to replicate the working request:

<!DOCTYPE html> <html> <head>     <title></title> </head> <body>     <form action="http://example.com/example/asdfas" method="post" enctype="multipart/form-data">         <label for="v1">Value 1</label>         <input id="v1" type="text" name="value_1">         <label for="v2">Value 2</label>         <input id="v2" type="text" name="value_2">         <input type="submit">     </form> </body> </html> 
like image 903
sornars Avatar asked Apr 16 '14 22:04

sornars


1 Answers

The solution is to use tuples when passing parameters to the files argument:

import requests requests.post('http://example.com/example/asdfas', files={'value_1': (None, '12345'), 'value_2': (None, '67890')}) 

Works as expected:

'Accept': '*/*',  'Accept-Encoding': 'gzip, deflate, compress',  'Content-Length': '228',  'User-Agent': 'python-requests/2.2.1 CPython/3.3.2 Windows/7',  'Content-Type': 'multipart/form-data; boundary=85e90a4bbb05474ca1e23dbebdd68ed9'  --85e90a4bbb05474ca1e23dbebdd68ed9 Content-Disposition: form-data; name="value_1"  12345 --85e90a4bbb05474ca1e23dbebdd68ed9 Content-Disposition: form-data; name="value_2"  67890 --85e90a4bbb05474ca1e23dbebdd68ed9-- 
like image 104
sornars Avatar answered Oct 06 '22 15:10

sornars