猿问

请求中的大写 URL 返回“名称无法解析”

我想从带有大写字符的 URL 获取数据。URL 基于 docker 主机名。requests 总是Name does not resolve在它降低 URL 时返回。


网址是http://gateway.Niedersachsen/api/bundeslaender。


ping gateway.Niedersachsen有效但ping gateway.niedersachsen无效。


我的 Python 请求代码:


url = f'http://gateway.Niedersachsen/api/wfs/insertGeometry'

r = requests.get(url)

出现以下错误:


requests.exceptions.ConnectionError: HTTPConnectionPool(host='gateway.niedersachsen', port=80): Max retries exceeded with url: /api/wfs/insertGeometry (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f5f5eb5a3c8>: Failed to establish a new connection: [Errno -2] Name does not resolve'))

我的版本:


$ python --version

Python 3.7.3


> requests.__version__

'2.21.0'


哆啦的时光机
浏览 180回答 1
1回答

三国纷争

RFC 3986第 6.2.2.1 节关于 URI 的说明:[...]的方案和主机是不区分大小写的,因此应被归一化到小写[...]。恕我直言,您的名称解析行为不正确,似乎有一个与 Docker 网络区分大小写相关的未决问题,我认为这里正在使用。requests, 分别&nbsp;urllib3, 尊重 RFC 建议,至少对于 HTTP 方案连接。就requests目前而言,似乎有四个相关的地方将主机名转换为小写。urllib3的实用程序类Url,它在requests'PreparedRequest实例执行prepare_url方法时发挥作用。通过映射_default_key_normalizer调用的函数PoolManagerkey_fn_by_scheme如果您的主机名包含非 ASCII 字符,它也会通过IDNA 编码传递,但在您的示例中并非如此。urllib31.22 版还lower()调用了ConnectionPool基类初始值设定项中的主机名。_ipv6_host显然,此规范化已移至1.23 版的功能。使用monkeypatching我似乎已经能够强制requests,resp。urllib3, 保留 URL 的主机名部分不变:import functoolsimport urllib3def _custom_key_normalizer(key_class, request_context):&nbsp; &nbsp; # basically a 1:1 copy of urllib3.poolmanager._default_key_normalizer&nbsp; &nbsp; # commenting out&nbsp;&nbsp; &nbsp; # https://github.com/urllib3/urllib3/blob/master/src/urllib3/poolmanager.py#L84&nbsp; &nbsp; #context['host'] = context['host'].lower()class ConnectionPool(object):&nbsp; &nbsp; def __init__(self, host, port=None):&nbsp; &nbsp; &nbsp; &nbsp; # complete copy of urllib3.connectionpool.ConnectionPool base class&nbsp; &nbsp; &nbsp; &nbsp; # I needed this due to my urllib3 version 1.22.&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; # If you have urllib3 >= 1.23 this is not necessary&nbsp; &nbsp; &nbsp; &nbsp; # remove the .lower() from&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; # https://github.com/urllib3/urllib3/blob/1.22/urllib3/connectionpool.py#L71&nbsp; &nbsp; &nbsp; &nbsp; self.host = urllib3.connectionpool._ipv6_host(host)urllib3.util.url.NORMALIZABLE_SCHEMES = (None,)# This is needed for urllib3 >= 1.23. The connectionpool module imports# NORMALIZABLE_SCHEMES before we can patch it, so we have to explicitly patch it againurllib3.connectionpool.NORMALIZABLE_SCHEMES = (None,)urllib3.poolmanager.key_fn_by_scheme['http'] = functools.partial(_custom_key_normalizer,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;urllib3.poolmanager.PoolKey)# just for urllib3 < 1.23urllib3.connectionpool.ConnectionPool = ConnectionPool# do not use anything that would import urllib3 before this point&nbsp; &nbsp;&nbsp;import requestsurl = f'http://gateway.Niedersachsen/api/wfs/insertGeometry'r = requests.get(url)我假设成功,因为我的错误消息显示连接池中使用的主机,仍然使用初始大写:requests.exceptions.ConnectionError: HTTPConnectionPool(host='gateway.Niedersachsen', port=80): [...]注意:直接使用可能有更简单的方法urllib3;我没有研究过这个。另外,如果有人知道使用 保留主机大写的更直接方法requests,请告诉我。
随时随地看视频慕课网APP

相关分类

Python
我要回答