I'm trying to make an API POST request using the Python requests library. I am passing through an Authorization
header but when I try debugging, I can see that the header is being dropped. I have no idea what's going on.
Here's my code:
def make_post_request():
access_token = get_access_token()
bearer_token = base64.b64encode(bytes("'Bearer {}'".format(access_token)), 'utf-8')
print bearer_token
headers = {'Content-Type': 'application/json', 'Authorization': bearer_token}
data = '{"FirstName" : "Jane", "LastName" : "Smith"}'
response = requests.post('https://myserver.com/endpoint', headers=headers, data=data)
print response.request.headers
print response.text
The result of print response.request.headers
is: {'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.4.3 CPython/2.7.9 Linux/4.1.19-v7+'}
and the request fails with an error message saying 'invalid session ID' - which isn't surprising given that the Authorization header isn't present in the request headers.
Something really confusing I noticed was that if I change the POST request to be a GET request, it passes the header through!
Why would this library be dropping the header for POST requests and how do I get this to work?
Using v2.4.3 of the requests lib and Python 2.7.9
In requests 2.4.3, the only place where reqeuests
removes the Authorization
header is when a request is redirected to a different host. This is the relevant code:
if 'Authorization' in headers: # If we get redirected to a new host, we should strip out any # authentication headers. original_parsed = urlparse(response.request.url) redirect_parsed = urlparse(url) if (original_parsed.hostname != redirect_parsed.hostname): del headers['Authorization']
In newer versions of requests
, the Authorization
header will be dropped in additional cases (for example if the redirect is from a secure to a non-secure protocol).
What probably happens in your case, is that your post request gets redirected to a different host. If you want to preserve authentication, requests allows you to do that only using a netrc
file. Sadly that will only allow you to use HTTP Basic Auth, which seems to not be your authentication method. In that case, the best solution is probably to subclass requests.Session
and override this behavior, like so:
from requests import Session
class NoRebuildAuthSession(Session):
def rebuild_auth(self, prepared_request, response):
"""
No code here means requests will always preserve your authorization when redirected.
Be careful not to leak your credentials to untrusted hosts!
"""
session = NoRebuildAuthSession()
response = session.post('https://myserver.com/endpoint', headers=headers, data=data)