使用请求时,Python超强制HTTP / 2

问题描述

我正在尝试将hyper.contrib HTTP20Adapterhere所述的requests模块一起使用,但是即使遵循了以这种方式使用HTTP / 2的示例,它仍然使用HTTP / 1.1。结果为ConnectionResetError,并且从未尝试使用HTTP / 2。如果我使用hyper HTTPConnection,它也使用HTTP / 1.1并失败。但是,如果我使用HTTP20Connection,它将使用HTTP / 2并成功。是否可以通过requests强制HTTP20Adapter仅使用HTTP / 2?

使用HTTPConnection进行首次测试。 Wireshark跟踪确认这导致HTTP / 1.1 GET和连接重置。

>>> from hyper import HTTPConnection
>>> c = HTTPConnection('10.11.22.33:8080')
>>> c.request('GET','/my/path/')
>>> resp = c.get_response()
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
  File "/root/Python/myApp/lib64/python3.6/site-packages/hyper/common/connection.py",line 129,in get_response
    return self._conn.get_response(*args,**kwargs)
  File "/root/Python/myApp/lib64/python3.6/site-packages/hyper/http11/connection.py",line 203,in get_response
    self._sock.fill()
  File "/root/Python/myApp/lib64/python3.6/site-packages/hyper/common/bufsocket.py",line 169,in fill
    raise ConnectionResetError()
ConnectionResetError

使用HTTP20Connection进行第二次测试。这导致HTTP / 2 GET请求和成功的响应。

>>> from hyper import HTTP20Connection
>>> c = HTTP20Connection('10.11.22.33:8080')
>>> c.request('GET','/my/path/')
1
>>> resp = c.get_response()
>>> print(resp.headers)
HTTPHeaderMap([(b'server',b'nginx/1.14.1'),(b'date',b'Wed,12 Aug 2020 13:29:34 GMT'),(b'content-type',b'application/problem+json'),(b'3gpp-sbi-message-priority',b'10'),(b'x-envoy-upstream-service-time',b'109')])

第三次测试,将requests与适配器一起使用。这也导致了HTTP / 1.1请求和ConnectionResetError。在网上看不到HTTP / 2。

>>> import requests
>>> from hyper.contrib import HTTP20Adapter
>>> 
>>> s = requests.Session()
>>> s.mount('http://10.11.22.33:8080',HTTP20Adapter())
>>> s
<requests.sessions.Session object at 0x7f68f3487f28>
>>> 
>>> 
>>> r = s.get('http://10.11.22.33:8080/my/path/')
Traceback (most recent call last):
  File "<stdin>",in <module>
  File "/root/Python/myApp/lib64/python3.6/site-packages/requests/sessions.py",line 543,in get
    return self.request('GET',url,**kwargs)
  File "/root/Python/myApp/lib64/python3.6/site-packages/requests/sessions.py",line 530,in request
    resp = self.send(prep,**send_kwargs)
  File "/root/Python/myApp/lib64/python3.6/site-packages/requests/sessions.py",line 643,in send
    r = adapter.send(request,**kwargs)
  File "/root/Python/myApp/lib64/python3.6/site-packages/hyper/contrib.py",line 80,in send
    resp = conn.get_response()
  File "/root/Python/myApp/lib64/python3.6/site-packages/hyper/common/connection.py",in fill
    raise ConnectionResetError()
ConnectionResetError

由于框架的其余部分正在使用requests模块,因此我真的需要进行最后的测试。

解决方法

我建议您在此处使用一个猴子补丁。

编写如下所示的自定义请求,以使用HTTP20Connection代替HTTP11Connection

from hyper.http20.connection import HTTP20Connection


def custom_request(self,method,url,body=None,headers=None):

    headers = headers or {}
    if self._conn.__class__.__name__ == 'HTTP11Connection':
        self._conn = HTTP20Connection(
                self._host,self._port,**self._h2_kwargs
                )
    try:
        return self._conn.request(
                method=method,url=url,body=body,headers=headers
        )
    except TLSUpgrade as e:
        assert e.negotiated in H2_NPN_PROTOCOLS
        self._conn = HTTP20Connection(
                self._host,**self._h2_kwargs
        )
        self._conn._sock = e.sock
        self._conn._send_preamble()
        return self._conn.request(
                method=method,headers=headers
        )

此后,您可以按以下步骤进行猴子补丁

from hyper.common.connection import HTTPConnection
HTTPConnection.request = custom_request

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...