У меня есть питон код, который выглядит следующим образом:Зрения повторы из запроса, отправленного с помощью urllib3.PoolManager без повторных попыток сконфигурированы
import urllib3
http = urllib3.PoolManager(cert_reqs='CERT_NONE')
...
full_url = 'https://[%s]:%d%s%s' % \
(address, port, base_uri, relative_uri)
kwargs = {
'headers': {
'Host': '%s:%d' % (hostname, port)
}
}
if data is not None:
kwargs['body'] = json.dumps(data, indent=2, sort_keys=True)
# Directly use request_encode_url instead of request because requests
# will try to encode the body as 'multipart/form-data'.
response = http.request_encode_url('POST', full_url, **kwargs)
log.debug('Received response: HTTP status %d. Body: %s' %
(response.status, repr(response.data)))
У меня есть строка журнала, который печатает один раз до кода, который выдает запрос , а линия log.debug('Received...')
печатает один раз. Однако на стороне сервера я иногда вижу два запроса (они оба - тот же запрос POST, который отправляется этим блоком кода), примерно на расстоянии 1-5 секунд. В таких случаях порядок событий выглядят следующим образом:
- Один запроса, отправленный из питона клиента
- Первого запрос получил
- Второго запроса получил
- Первого ответа, отправленный со статусом 200 и HTTP лицом, указывающим успех
- второй ответ, отправленный со статусом 200 и HTTP лица с указанием отказа
- Python клиент получает второй réponse
Я попытался надежно воспроизвести его, спянув на сервере (предположив, что может быть тайм-аут, который вызывает повтор), но не увенчался успехом. Я считаю, что дублирование вряд ли произойдет на сервере, потому что это просто базовый сервер Scala Spray и не видел этого с другими клиентами. Рассматривая исходный код для PoolManager
, я не могу найти место, где будут включены повторы. Существует механизм повторений, заданный с необязательным параметром, но этот необязательный параметр не используется в приведенном выше коде.
Есть ли у кого-нибудь идеи, откуда этот дополнительный запрос?
EDIT: @shazow дал указатель о retries
, имеющий значение по умолчанию 3, но я изменил код, как предложил и получил следующее сообщение об ошибке:
Traceback (most recent call last):
File "my_file.py", line 23, in <module>
response = http.request_encode_url('GET', full_url, **kwargs)
File "/usr/lib/python2.7/dist-packages/urllib3/request.py", line 88, in request_encode_url
return self.urlopen(method, url, **urlopen_kw)
File "/usr/lib/python2.7/dist-packages/urllib3/poolmanager.py", line 145, in urlopen
conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)
File "/usr/lib/python2.7/dist-packages/urllib3/poolmanager.py", line 119, in connection_from_host
pool = self._new_pool(scheme, host, port)
File "/usr/lib/python2.7/dist-packages/urllib3/poolmanager.py", line 86, in _new_pool
return pool_cls(host, port, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'retries'`
Edit # 2: Следующие изменения в kwargs
кажется работа для меня:
import urllib3
http = urllib3.PoolManager(cert_reqs='CERT_NONE')
...
full_url = 'https://[%s]:%d%s%s' % \
(address, port, base_uri, relative_uri)
kwargs = {
'headers': {
'Host': '%s:%d' % (hostname, port)
},
'retries': 0
}
if data is not None:
kwargs['body'] = json.dumps(data, indent=2, sort_keys=True)
# Directly use request_encode_url instead of request because requests
# will try to encode the body as 'multipart/form-data'.
response = http.request_encode_url('POST', full_url, **kwargs)
log.debug('Received response: HTTP status %d. Body: %s' %
(response.status, repr(response.data)))
Я вижу, что это задокументировано, но по какой-то причине, как упоминалось в моем редактировании, это не сработало (возможно, это было добавлено в более поздней версии urllib3). Для меня работала установка «повторов» в 'kwargs' (см. Edit # 2). – jonderry
То, что вы сделали, должно быть эквивалентно передаче retries = 0, которое, как мне кажется, в этом случае считается таким же, как False. Всегда полезно узнать, какую версию urllib3 вы имеете в виду, иначе я предполагаю, что это последняя. :) – shazow