pythonpython-requestscontent-lengthhttp-content-length

How not to let python requests calculate content-length and use the provided one?


We have some custom module where we have redefined open, seek, read, tell functions to read only a part of file according to the arguments.

But, this logic overrides the default tell and python requests is trying to calculate the content-length which involves using tell(), which then redirects to our custom tell function and the logic is somewhere buggy and returns a wrong value. And I tried some changes, it throws error.

Found the following from models.py of requests:

 def prepare_content_length(self, body):
        if hasattr(body, 'seek') and hasattr(body, 'tell'):
            body.seek(0, 2)
            self.headers['Content-Length'] = builtin_str(body.tell())
            body.seek(0, 0)
        elif body is not None:
            l = super_len(body)
            if l:
                self.headers['Content-Length'] = builtin_str(l)
        elif (self.method not in ('GET', 'HEAD')) and (self.headers.get('Content-Length') is None):
            self.headers['Content-Length'] = '0'

For now, I am not able to figure out where's the bug and stressed out to investigate more and fix it. And everything else work except content-length calculation by python requests.

So, I have created my own definition for finding content-length. And I have included the value in requests header. But, the request is still preparing the content-length and throwing error.

How can I restrict not preparing content-length and use the specified content-length?


Solution

  • Requests lets you modify a request before sending. See Prepared Requests.

    For example:

    from requests import Request, Session
    
    s = Session()
    
    req = Request('POST', url, data=data, headers=headers)
    prepped = req.prepare()
    
    # do something with prepped.headers
    prepped.headers['Content-Length'] = your_custom_content_length_calculation()
    
    resp = s.send(prepped, ...)
    

    If your session has its own configuration (like cookie persistence or connection-pooling), then you should use s.prepare_request(req) instead of req.prepare().