What does 'RemoteProtocolError: illegal request line' mean?

What does 'RemoteProtocolError: illegal request line' mean?

我正在 Apple Push Notifications 上处理推送通知,它仅使用 HTTP/2(因此无法使用 requests)并保留得到 httpx.RemoteProtocolError: illegal request line。我不知道这是什么意思:

>>> import httpx
>>> httpx.__version__
'0.18.2'
>>> httpx.post('https://api.development.push.apple.com:443/3/device/<device-token>')
Traceback (most recent call last):
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_transports/default.py", line 61, in map_httpcore_exceptions
    yield
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_transports/default.py", line 181, in handle_request
    status_code, headers, byte_stream, extensions = self._pool.handle_request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpcore/_sync/connection_pool.py", line 237, in handle_request
    response = connection.handle_request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpcore/_sync/connection.py", line 148, in handle_request
    return self.connection.handle_request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpcore/_sync/http11.py", line 128, in handle_request
    ) = self._receive_response(timeout)
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpcore/_sync/http11.py", line 189, in _receive_response
    event = self._receive_event(timeout)
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpcore/_sync/http11.py", line 222, in _receive_event
    event = self._h11_state.next_event()
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.RemoteProtocolError: illegal request line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_api.py", line 304, in post
    return request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_api.py", line 100, in request
    return client.request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_client.py", line 785, in request
    return self.send(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_client.py", line 871, in send
    response = self._send_handling_auth(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_client.py", line 907, in _send_handling_auth
    response = self._send_handling_redirects(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_client.py", line 943, in _send_handling_redirects
    response = self._send_single_request(request, timeout)
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_client.py", line 977, in _send_single_request
    (status_code, headers, stream, extensions) = transport.handle_request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_transports/default.py", line 181, in handle_request
    status_code, headers, byte_stream, extensions = self._pool.handle_request(
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/martin/.pyenv/versions/3.8.9/lib/python3.8/site-packages/httpx/_transports/default.py", line 78, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.RemoteProtocolError: illegal request line

我该如何进一步调查?问题是什么? (我已经删除了这个问题的 headers / 有效负载 / 设备令牌;我一直遇到这个问题)

卷曲

使用 curl 我得到了预期的结果:

curl -X POST https://api.development.push.apple.com:443/3/device/adsf -v
*   Trying 17.188.138.70:443...
* TCP_NODELAY set
* Connected to api.development.push.apple.com (17.188.138.70) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
*  start date: Feb  8 21:41:22 2021 GMT
*  expire date: Mar 10 21:41:22 2022 GMT
*  subjectAltName: host "api.development.push.apple.com" matched cert's "api.development.push.apple.com"
*  issuer: CN=Apple Public Server RSA CA 12 - G1; O=Apple Inc.; ST=California; C=US
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5606c3af1e10)
> POST /3/device/adsf HTTP/2
> Host: api.development.push.apple.com
> user-agent: curl/7.68.0
> accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 1)!
< HTTP/2 403 
< apns-id: DFA9D8D5-D99D-26B0-9EA3-95076FF3B575
< 
* Connection #0 to host api.development.push.apple.com left intact
{"reason":"MissingProviderToken"}

与HTTPX_LOG_LEVEL=trace

httpx docs on environment variables

HTTPX_LOG_LEVEL=trace python example.py
trace
TRACE [2021-09-07 15:46:26] httpx._config - load_ssl_context verify=True cert=None trust_env=True http2=False
TRACE [2021-09-07 15:46:26] httpx._config - load_verify_locations cafile=/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/certifi/cacert.pem
TRACE [2021-09-07 15:46:26] httpcore._sync.connection_pool - get_connection_from_pool=(b'https', b'api.development.push.apple.com', 443)
TRACE [2021-09-07 15:46:26] httpcore._sync.connection_pool - created connection=<SyncHTTPConnection [Connecting]>
TRACE [2021-09-07 15:46:26] httpcore._sync.connection_pool - adding connection to pool=<SyncHTTPConnection [Connecting]>
TRACE [2021-09-07 15:46:26] httpcore._sync.connection - open_socket origin=(b'https', b'api.development.push.apple.com', 443) timeout={'connect': 5.0, 'read': 5.0, 'write': 5.0, 'pool': 5.0}
TRACE [2021-09-07 15:46:27] httpcore._sync.connection - create_connection socket=<httpcore._backends.sync.SyncSocketStream object at 0x7fdbdc632cd0> http_version='HTTP/1.1'
TRACE [2021-09-07 15:46:27] httpcore._sync.connection - connection.handle_request method=b'POST' url=(b'https', b'api.development.push.apple.com', None, b'/3/device/%3Cdevice-token%3E') headers=[(b'Host', b'api.development.push.apple.com'), (b'Content-Length', b'0'), (b'Accept', b'*/*'), (b'Accept-Encoding', b'gzip, deflate'), (b'Connection', b'keep-alive'), (b'User-Agent', b'python-httpx/0.19.0')]
TRACE [2021-09-07 15:46:27] httpcore._sync.http11 - send_request method=b'POST' url=(b'https', b'api.development.push.apple.com', None, b'/3/device/%3Cdevice-token%3E') headers=[(b'Host', b'api.development.push.apple.com'), (b'Content-Length', b'0'), (b'Accept', b'*/*'), (b'Accept-Encoding', b'gzip, deflate'), (b'Connection', b'keep-alive'), (b'User-Agent', b'python-httpx/0.19.0')]
TRACE [2021-09-07 15:46:27] httpcore._sync.http11 - send_data=Data(<0 bytes>)
TRACE [2021-09-07 15:46:27] httpcore._sync.connection_pool - remove from pool connection=<SyncHTTPConnection [HTTP/1.1, ACTIVE]>
TRACE [2021-09-07 15:46:27] httpcore._sync.connection_pool - removing connection from pool=<SyncHTTPConnection [HTTP/1.1, ACTIVE]>
Traceback (most recent call last):
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_transports/default.py", line 61, in map_httpcore_exceptions
    yield
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_transports/default.py", line 180, in handle_request
    status_code, headers, byte_stream, extensions = self._pool.handle_request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpcore/_sync/connection_pool.py", line 237, in handle_request
    response = connection.handle_request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 148, in handle_request
    return self.connection.handle_request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 128, in handle_request
    ) = self._receive_response(timeout)
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 189, in _receive_response
    event = self._receive_event(timeout)
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpcore/_sync/http11.py", line 222, in _receive_event
    event = self._h11_state.next_event()
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/contextlib.py", line 135, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc) from None
httpcore.RemoteProtocolError: illegal request line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/moose/example.py", line 5, in <module>
    print(httpx.post('https://api.development.push.apple.com:443/3/device/<device-token>'))
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_api.py", line 304, in post
    return request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_api.py", line 100, in request
    return client.request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_client.py", line 787, in request
    return self.send(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_client.py", line 878, in send
    response = self._send_handling_auth(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_client.py", line 908, in _send_handling_auth
    response = self._send_handling_redirects(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_client.py", line 947, in _send_handling_redirects
    response = self._send_single_request(request, timeout)
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_client.py", line 983, in _send_single_request
    (status_code, headers, stream, extensions) = transport.handle_request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_transports/default.py", line 180, in handle_request
    status_code, headers, byte_stream, extensions = self._pool.handle_request(
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/contextlib.py", line 135, in __exit__
    self.gen.throw(type, value, traceback)
  File "/home/moose/.pyenv/versions/3.9.1/lib/python3.9/site-packages/httpx/_transports/default.py", line 78, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.RemoteProtocolError: illegal request line

问题是您需要安装额外的依赖项并显式启用 http2:

$ pip install httpx[http2]

import httpx
client = httpx.Client(http2=True)
client.post('https://api.development.push.apple.com:443/3/device/<device-token>')