【问题标题】:Python hyper force HTTP/2 when using requests使用请求时 Python 超级强制 HTTP/2
【发布时间】:2020-12-02 06:48:43
【问题描述】:

我正在尝试将hyper.contrib HTTP20Adapterrequests 模块一起使用,如here 所述,但即使遵循以这种方式使用HTTP/2 的示例,它仍然使用HTTP/1.1。这导致ConnectionResetError 并且从未尝试过HTTP/2。如果我使用hyper HTTPConnection,它也使用 HTTP/1.1 并且失败。但是如果我使用HTTP20Connection,它会使用 HTTP/2 并成功。有没有办法强制 requestsHTTP20Adapter 只使用 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>", line 1, 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", 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

我真的需要让最后一个测试工作,因为我的框架的其余部分正在使用requests 模块。

【问题讨论】:

    标签: python http2 httpconnection hyper


    【解决方案1】:

    我建议你在这里使用猴子补丁。

    编写如下所示的自定义请求以使用 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._port, **self._h2_kwargs
            )
            self._conn._sock = e.sock
            self._conn._send_preamble()
            return self._conn.request(
                    method=method, url=url, body=body, headers=headers
            )
    

    在此之后你可以按如下方式进行monkeypatch

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-16
      • 2016-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多