Python请求可以';t使用同一密钥发送多个标头

Python请求可以';t使用同一密钥发送多个标头,python,python-requests,Python,Python Requests,我正在尝试向服务器发送一个get请求,其中包含两个标题,它们具有相同的名称,但值不同: url = 'whatever' headers = {'X-Attribute':'A', 'X-Attribute':'B'} requests.get(url, headers = headers) 这显然不起作用,因为headers字典不能包含两个键X-Attribute 我能做些什么吗?比如,我能不能把标题作为字典以外的东西传递?以这种方式发送请求是服务器的一项功能,我无法更改它。requests

我正在尝试向服务器发送一个get请求,其中包含两个标题,它们具有相同的名称,但值不同:

url = 'whatever'
headers = {'X-Attribute':'A', 'X-Attribute':'B'}
requests.get(url, headers = headers)
这显然不起作用,因为headers字典不能包含两个键
X-Attribute


我能做些什么吗?比如,我能不能把标题作为字典以外的东西传递?以这种方式发送请求是服务器的一项功能,我无法更改它。

requests
将请求头存储在
dict
中,这意味着每个头只能出现一次。因此,如果不更改
请求
库本身,就不可能发送具有相同名称的多个标头


但是,如果服务器是,则它必须能够接受相同的头,并使用逗号分隔的单个值列表。

请求现在将所有头(发送和接收)以不区分大小写的方式存储在字典中。但除此之外,打开python控制台并编写:

headers = {'X-Attribute':'A', 'X-Attribute':'B'}
你得到的是未定义的行为。(它可能看起来是可复制的,但完全没有定义。)因此,在这种情况下,您真正发送给请求的是:

{'X-Attribute': 'A'}  # or {'X-Attribute': 'B'}, we can never be certain which it will be
您可以尝试(但不起作用)的是:

但至少这将是完全定义的行为(您将始终发送B)。正如@mata所建议的,如果您的服务器符合HTTP/1.1标准,那么您可以做以下操作:

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)

我希望这对您有所帮助。

请求在引擎盖下使用urllib2.urlencode(或类似的东西)对标题进行编码

这意味着元组列表可以作为有效负载参数而不是字典发送,从而将头列表从字典施加的唯一键约束中解放出来。发送元组列表在urlib2.urlencode文档中有描述

以下代码将解决问题,而不会造成扁平化或恶意攻击:

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

我对params也有同样的问题:

以上这些都不适合我

有效的方法是从头开始建立一个列表

    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)

我不知道5年后你是否仍然有这个问题,但我也在努力解决同样的问题。以下是对我有效的方法:

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

为什么要这样做?我向其发送请求的服务器期望这样做。它根据传递给它的完整属性集过滤响应,属性的形式为
X-Attribute:name=value
,这很有用。遗憾的是,服务器看起来不兼容!我从未建议将此作为答案,但您可以尝试利用请求不会自动转义传递的头dict的内容这一事实,并传递
headers={'X-Attribute':'name=value\r\nX Attribute:name=value'}
。然而,这不是一个很好的解决方案……我已经看到,在实践中,HTTP服务器往往会限制头行的长度。如果完整的逗号分隔列表对于一行来说太长怎么办?这似乎需要解决原始问题。@rspeer然后您应该告诉该服务器的管理员它不符合要求。最好的解决办法是像现在这样加入他们。由于这种情况非常罕见,我们没有将此功能作为高优先级。这似乎不适用于我的请求版本(2.7.0)。我几年前就离开了该项目,但我认为您的建议正是@mata最初建议的……需要兼容的服务器来接受逗号分隔的值。服务器在许多方面都不兼容,包括不接受这些。问题与头相关,而不是参数。因此,这对标题不起作用。
url = 'whatever'
headers = {'X-Attribute': "A,B"}
requests.get(url, headers = headers)