python请求的URL规则
最近,我将客户端上载代码从python请求的URL规则,python,python-requests,Python,Python Requests,最近,我将客户端上载代码从HTTPConnection移植到请求。上载图像时: file_name ='/path/to/216169_1286900924tait.jpg?pt=5&ek=1' 存储在磁盘上的映像实际上就是名称,我想用相同的路径和名称将其上载到远程服务器,因此我构建了如下请求: url = 'http://host/bucket_name/%s' % (file_name) headers = {...} # some other headers with open(
HTTPConnection
移植到请求
。上载图像时:
file_name ='/path/to/216169_1286900924tait.jpg?pt=5&ek=1'
存储在磁盘上的映像实际上就是名称,我想用相同的路径和名称将其上载到远程服务器,因此我构建了如下请求:
url = 'http://host/bucket_name/%s' % (file_name)
headers = {...} # some other headers
with open(file_name, 'rb') as fd:
data = fd.read()
r = requests.put(url, data=data, headers=headers)
assert(r.status_code==200)
....
但发送到服务器的请求更改为:
/path/to/216169_1286900924tait.jpg
请求
应该将尾部编码为%3Fpt%3D5%26ek%3D1
,但似乎请求
对url
的url编码没有任何作用,我认为它可能会将?pt=5&ek=1
模式与请求参数匹配,如何使请求
在没有模式匹配的情况下盲目转换url
更新:
服务器获取修剪后的url并使用它计算签名,因此与我计算的签名不匹配,所以403返回 您可能在构建URL时遇到问题:
>>> payload = {'pt': 5, 'ek': '1'}
>>> r = requests.get('http://host/bucket_name/file_name', params=payload)
如果您调用print(r.url),您应该拥有正确的表单。为什么
请求
应该假定对查询参数进行编码?它不知道您不希望URL的这一部分被视为查询字符串。此外,请求会按原样发送到服务器,查询字符串不会像您建议的那样被省略。您可以使用nc
验证:
# run nc server
$ nc -l 1234
# then send request from Python
>>> requests.put('http://localhost:1234/path/to/216169_1286900924tait.jpg?pt=5&ek=1', data='any old thing')
nc
将显示请求:
PUT /path/to/216169_1286900924tait.jpg?pt=5&ek=1 HTTP/1.1
Host: localhost:1234
Content-Length: 13
User-Agent: python-requests/2.9.1
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate
any old thing
生成此请求:
PUT /path/to/216169_1286900924tait.jpg?pt=5&ek=1 HTTP/1.1
Host: localhost:1234
Accept-Encoding: identity
Content-Length: 18
hello from httplib
PUT/path/to/216169_1286900924tait.jpg?pt=5&ek=1http/1.1
主机:localhost:1234
接受编码:标识
内容长度:18
您好,来自httplib
请注意,URL的发送方式没有区别。我深入研究了
请求
源代码,找到了以下代码行(是的,请求
基于urllib3
):
在构建url字符串时,您应该手动对url进行url编码,例如:
>>> path = '''~!@#$^&*()_+|}{":?><`-=\\][\';.,'''
>>> url = 'http://host.com/bucket/%s' % path
>>> urllib3.util.parse_url(url)
>>> Url(scheme='http', auth=None, host='host.com', port=None, path='/bucket/~!@', query=None, fragment='$^&*()_+|}{":?><`-=B%7C%7D%7B%22%3A%3F%3E%3C%60-%3D%5C%5D%5B%27%3B.%2C')
这就是我想要的。但是,如果要将tome unicode字符传递到
路径
,则不需要对它们进行编码,它们会自动转换为%xx%xx
格式。但是url编码对于您传入url的任何字符都是一个很好的建议。我不确定我是否理解“对url编码不做任何事情”或您所说的“模式匹配”是什么意思。您为文件名
分配内容的行不能是有效的Python,因为没有引号。您的文件是否真的保存在磁盘上,文件名中有查询参数?我不确定所有的文件系统都允许这些字符。你的更新提到了一个签名,但我不知道这意味着什么。路径不同,因为有一个
表示URL的其余部分是一个签名。在您的示例中,这两个URL实际上是不同的。我认为quote()
URL的查询部分是可以的,但是#
很重要。顺便问一下:您是如何使用HTTPConnection
的?您是否quote()
查询字符串?
scheme, auth, host, port, path, query, fragment = urllib3.util.parse_url(url)
>>> path = '''~!@#$^&*()_+|}{":?><`-=\\][\';.,'''
>>> url = 'http://host.com/bucket/%s' % path
>>> urllib3.util.parse_url(url)
>>> Url(scheme='http', auth=None, host='host.com', port=None, path='/bucket/~!@', query=None, fragment='$^&*()_+|}{":?><`-=B%7C%7D%7B%22%3A%3F%3E%3C%60-%3D%5C%5D%5B%27%3B.%2C')
>>> path = '''~!@#$^&*()_+|}{":?><`-=\\][\';.,'''
>>> url = 'http://host.com/bucket/%s' % (urllib.quote(path, ''))
>>> print url
>>> http://host.com/bucket/%7E%21%40%23%24%25%5E%26%2A%28%29_%2B%7C%7D%7B%22%3A%3F%3E%3C%60-%3D%5C%5D%5B%27%3B.%2C
>>> urllib3.util.parse_url(url)
>>> Url(scheme='http', auth=None, host='host.com', port=None, path='/bucket/%7E%21%40%23%24%25%5E%26%2A%28%29_%2B%7C%7D%7B%22%3A%3F%3E%3C%60-%3D%5C%5D%5B%27%3B.%2C', query=None, fragment=None)