Python requests cannot send multiple headers with the same key

I am trying to send a receive request to a server with two headers with the same name but different values:

url = 'whatever' headers = {'X-Attribute':'A', 'X-Attribute':'B'} requests.get(url, headers = headers) 

This clearly does not work, since the header dictionary cannot contain two X-Attribute keys.

Is there anything I can do, i.e. convey headers as something other than a dictionary? The requirement to send requests this way is a feature of the server, and I cannot change it.

+4
source share
4 answers

requests stores request headers in a dict , which means that each header can only appear once. Therefore, without making changes to the requests library, you will not be able to send multiple headers with the same name.

However, if the HTTP1.1 server is compatible , it should be able to accept the same thing as a single header with a comma-separated list of single values.

+6
source

the request uses urllib2.urlencode under the hood (or something similar) to encode the headers.

This means that the list of tuples can be sent as a payload argument instead of a dictionary, freeing the list of headers from the unique key constraint imposed by the dictionary. Sending a list of tuples is described in the urlib2.urlencode documentation. http://docs.python.org/2/library/urllib.html#urllib.urlencode

The following code will solve the problem without anti-aliasing or dirty hacks:

 url = 'whatever' headers = [('X-Attribute', 'A'), ('X-Attribute', 'B')] requests.get(url, headers = headers) 
+4
source

Requests currently store all headers (sent and received) as invisibly in dictionaries. Other than that, however, open the python console and write:

 headers = {'X-Attribute':'A', 'X-Attribute':'B'} 

What you get is undefined behavior. (This may seem reproducible, but it is completely undefined.) So you are really sending requests in this instance:

 {'X-Attribute': 'A'} # or {'X-Attribute': 'B'}, we can never be certain which it will be 

What could you try (but failed):

 headers = [('X-Attribute', 'A'), ('X-Attribute', 'B')] 

But at least it will be a completely specific behavior (you will always send B). As @mata suggested, if your server is HTTP/1.1 compliant, then you can do this:

 import collections def flatten_headers(headers): for (k, v) in list(headers.items()): if isinstance(v, collections.Iterable): headers[k] = ','.join(v) headers = {'X-Attribute': ['A', 'B', ..., 'N']} flatten_headers(headers) requests.get(url, headers=headers) 

Hope this helps you.

+2
source

I had the same problem with the parameters:

None of the above worked for me.

What worked with listing from scratch

  params=[] params.append([]) params.append([]) params[0].append('X-Attribute') params[0].append(var1) params[1].append('X-Attribute') params[1].append(var2) requests.get(url, params=params) 
0
source

Source: https://habr.com/ru/post/1483124/


All Articles