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

Question:

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?

Asked By: GP92

||

Answers:

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().

Answered By: nofinator