pythonhttprestpython-requests

Python requests: How to PUT a string in body?


I need to PUT data from a string (no dict) as the body of the call to a REST API.
When I call

r = requests.put(url, data = string)

then I can see in r.request.body after this call that it is None. Also, the server responds with a "411 Length Required" error.

However, when I try it with a dict instead of a string then it works, as the server responds with the correct JSON data. Moreover, in that case I can see in r.request.body the correct data.

Any ideas?

PS: I am using Python 2.7.3 and Python-requests 1.2.0


Solution

  • Even after three attempts to clarify the question, it still isn't clear what you're asking here, but I can try to throw out enough info that you can figure out the answer.

    First, r = requests.put(url, data = string) returns a Response, which doesn't have a body, but it does have a request, and a history of 0 or more redirect requests, all of which are PreparedRequest objects, which do have body attributes.

    On the other hand, if you did r.requests.Request(method='PUT', url=url, data=string), that would return a Request, which has to be prepare()d before it has a body.

    Either way, if I do a simple test and look at the results, I find that the body is always correct:

    >>> resp = requests.put('http://localhost/nosuchurl', data='abc')
    >>> resp.request.body
    'abc'
    >>> resp = requests.put('http://localhost/redirect_to_https', data='abc')
    >>> resp.history[-1].request.body
    'abc'
    >>> req = requests.Request(method='PUT', url='http://localhost/nosuchurl', data='abc')
    >>> preq = req.prepare()
    >>> preq.body
    'abc'
    

    My best guess is that you need to be looking at resp.history[0].request.body, but you're looking at resp.request.body, or something similar.

    If Redirection and History in the quickstart tutorial doesn't help, read the detailed API docs, or just experiment with all of them until you figure it out.

    Or do this:

    resp = request.put('http://localhost/nosuchurl', data='abc', allow_redirects=False)
    

    And then do the redirect-handling manually.