7

I'm trying to make a post, however each time I did it, I would get a 411 response error. I'm using the requests library in python.

In [1]: r.post(url)
Out[1]: <Response [411]>

So then I specified the content length h = {'content-length' : '0'} and try again.

In [2]: r.post(url,h)
Out[2]: <Response [200]>

So great, I get a success, however none of the information is posted in.

I think I need to calculate the content-length, which makes sense as it could be "cutting-off" the post.

So my question is, given a url www.example.com/import.php?key=value&key=value how can I calculate the content-length? (in python if possible)

Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
tshauck
  • 20,746
  • 8
  • 36
  • 36
  • 1
    Does it work if you just use `urllib`? (I'm surprised that `request` doesn't automatically fill in the `Content-Length` header, given that it's based on `httplib` which does.) – Katriel Mar 13 '12 at 22:19
  • Please add information about version of Requests you're using. Also please include test case which results in 411 response's status code. – Piotr Dobrogost Apr 18 '12 at 20:44
  • [Visit this link to get answer of your query](http://stackoverflow.com/a/3854983/5354673) – Shriyansh Agrawal Feb 26 '17 at 12:44

3 Answers3

1

Sending POST request with empty body is perfectly legal as long as the Content-Length header is being sent and set to 0. Requests normally calculate the value for Content-Length header. The behavior you observe is probably due to issue 223 - Content-Length is missing. Although the bug is not closed it looks like the issue was fixed:

C:\>python
Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.__version__
'0.11.1'
>>> r = requests.post('http://httpbin.org/post?key1=valueA&key2=valueB')
>>> print r.content
{
  "origin": "77.255.249.138",
  "files": {},
  "form": {},
  "url": "http://httpbin.org/post?key1=valueA&key2=valueB",
  "args": {
    "key2": "valueB",
    "key1": "valueA"
  },
  "headers": {
    "Content-Length": "0",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Connection": "keep-alive",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.11.1",
    "Host": "httpbin.org",
    "Content-Type": ""
  },
  "json": null,
  "data": ""
}
Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
1

It looks strange that you use post method without the data argument (but put data in url).

Look at the example from the official requests documentation :

>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print r.text
{
  "origin": "179.13.100.4",
  "files": {},
  "form": {
    "key2": "value2",
    "key1": "value1"
  },
  "url": "http://httpbin.org/post",
  "args": {},
  "headers": {
    "Content-Length": "23",
    "Accept-Encoding": "identity, deflate, compress, gzip",
    "Accept": "*/*",
    "User-Agent": "python-requests/0.8.0",
    "Host": "127.0.0.1:7077",
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "data": ""
}
Leonid Shvechikov
  • 3,927
  • 2
  • 17
  • 14
0

If you hit the same API from postman it will work. The reason is because postman automatically includes content-length in the header while calling an API. If you try unchecking content-length in postman then it doesn't work.

This issue is something that happens intermittently. You will still get 200 RESPONSE if you hit without content-length(at times) and 400 or someother whichever it throws when body is not present.

So the hack here is, The API host which you're trying to hit will sometimes try to figure the content length on it's own and sometimes when heavy traffic it is actually configured to not utilise it's power/time to calculate the content-length hence it believes there is no body when content-length is not given. So if you give content-length : 0 then it will actually calculate the content-length every time because during the transportation of data it can compress and uncompress.

Also

while(times--):
    requests.post(url,headers)

The above didn't work but the below has worked.

while(times--):
    requests.post(url,headers)
    time.sleep(2.5)