Прописный URL в запросах возвращает «Имя не разрешается» - PullRequest
0 голосов
/ 10 апреля 2019

Я хотел бы получить данные из URL с заглавными буквами.URL основан на имени хоста докера.запросы всегда возвращают Name does not resolve при понижении URL.

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'

1 Ответ

3 голосов
/ 10 апреля 2019

RFC 3986 В разделе 6.2.2.1 говорится об URI:

[...] схема и хост не чувствительны к регистру , и поэтому следует нормализовать в нижнем регистре [...].

ИМХО, ваше разрешение имени ведет себя некорректно, и, кажется, существует открытая проблема , связанная с чувствительностью к регистру для сети Docker, которая, как я предполагаю, используется здесь.

requests, соотв. urllib3, соблюдает рекомендацию RFC, по крайней мере для соединений по схеме HTTP. Что касается requests, то, по-видимому, существует четыре соответствующих места, где имена хостов преобразуются в нижний регистр.

  1. urllib3 служебный класс Url, который вступает в игру, когда экземпляр requests 'PreparedRequest выполняет метод prepare_url.
  2. функция _default_key_normalizer, вызываемая PoolManager через отображение key_fn_by_scheme
  3. в случае, если ваше имя хоста содержит не-ASCII-символы, оно также проходит через кодировку IDNA, но в вашем примере это не так.
  4. urllib3 версия 1.22 также имела вызов lower() для имени хоста в инициализаторе базового класса ConnectionPool. Эта нормализация была перенесена в функцию _ipv6_host начиная с версии 1.23.

Используя monkeypatching, я, кажется, смог заставить requests, соответственно. urllib3, чтобы оставить часть имени хоста URL нетронутой:

import functools
import urllib3

def _custom_key_normalizer(key_class, request_context):
    # basically a 1:1 copy of urllib3.poolmanager._default_key_normalizer
    # commenting out 
    # https://github.com/urllib3/urllib3/blob/master/src/urllib3/poolmanager.py#L84
    #context['host'] = context['host'].lower()

class ConnectionPool(object):
    def __init__(self, host, port=None):
        # complete copy of urllib3.connectionpool.ConnectionPool base class
        # I needed this due to my urllib3 version 1.22. 
        # If you have urllib3 >= 1.23 this is not necessary
        # remove the .lower() from 
        # https://github.com/urllib3/urllib3/blob/1.22/urllib3/connectionpool.py#L71
        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 again
urllib3.connectionpool.NORMALIZABLE_SCHEMES = (None,)
urllib3.poolmanager.key_fn_by_scheme['http'] = functools.partial(_custom_key_normalizer, 
                                                                 urllib3.poolmanager.PoolKey)
# just for urllib3 < 1.23
urllib3.connectionpool.ConnectionPool = ConnectionPool

# do not use anything that would import urllib3 before this point    
import requests
url = f'http://gateway.Niedersachsen/api/wfs/insertGeometry'
r = requests.get(url)

Я предполагаю успех, потому что мое сообщение об ошибке, отображающее хост, используемый в пуле соединений, все еще использует начальную заглавную букву:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='gateway.Niedersachsen', port=80): [...]

Примечание:
Возможно, будет еще более простой способ, если использовать urllib3 напрямую; Я не рассматривал это.
Кроме того, если кто-то знает более простой способ сохранения капитализации хоста, используя requests, , пожалуйста, , дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...