Search code examples
pythonhttpsslhttp2

Python `hyper` library do not work on my environment


I have problem with running Python hyper library that adds support for HTTP/2 protocol.

On my Fedora machine I installed it with pip and pip3 to use it with Python 2.7.8 and Python 3.4.1. Then I copied test script that connects with twitter:

from hyper import HTTP20Connection

conn = HTTP20Connection('twitter.com:443')
conn.request('GET', '/')
resp = conn.getresponse()

print(resp.read())

I run it using Python 2.7.8 and it ends with error:

[mn:/plib] 1 ‡ python hyper_test.py 
Traceback (most recent call last):
  File "hyper_test.py", line 4, in <module>
    conn.request('GET', '/')
  File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 149, in request
    self.endheaders(message_body=body, final=True, stream_id=stream_id)
  File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 310, in endheaders
    self.connect()
  File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 215, in connect
    self._recv_cb()
  File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 580, in _recv_cb
    self._consume_single_frame()
  File "/usr/lib/python2.7/site-packages/hyper/http20/connection.py", line 496, in _consume_single_frame
    frame, length = Frame.parse_frame_header(header)
  File "/usr/lib/python2.7/site-packages/hyper/http20/frame.py", line 52, in parse_frame_header
    frame = FRAMES[type](stream_id)
KeyError: 80

It ends with different error with Python 3.4.1:

[mn:/plib] 1 ‡ python3 hyper_test.py 
Traceback (most recent call last):
  File "hyper_test.py", line 4, in <module>
    conn.request('GET', '/')
  File "/usr/lib/python3.4/site-packages/hyper/http20/connection.py", line 149, in request
    self.endheaders(message_body=body, final=True, stream_id=stream_id)
  File "/usr/lib/python3.4/site-packages/hyper/http20/connection.py", line 310, in endheaders
    self.connect()
  File "/usr/lib/python3.4/site-packages/hyper/http20/connection.py", line 204, in connect
    sock = wrap_socket(sock, self.host)
  File "/usr/lib/python3.4/site-packages/hyper/http20/tls.py", line 44, in wrap_socket
    assert ssl_sock.selected_npn_protocol() in H2_NPN_PROTOCOLS
AssertionError

What can cause such problems on my environment?


Solution

  • The first problem is caused by hyper not supporting Python 2.7.8.

    This is because the standard library's SSL module is terrible in Python 2.7.8, and lacks support for many features we need, including SSL Contexts, NPN, and ALPN. PyOpenSSL was intended to be used to bridge the gap, but my pull requests adding NPN and ALPN support to PyOpenSSL have languished unmerged for more than 9 months.

    If you'd like to use hyper with Python 2.7, you will need to use version 2.7.9, whose standard library SSL module is vastly improved.

    As for Python 3.4, that error is because Twitter has failed to negotiate HTTP/2 with us. That's somewhat unexpected, because it seems to be working fine for me from the UK this morning. Do you have some kind of intermediate MITM proxy?

    I do need to make that error clearer, so I consider that to be a bug: I'll update it from an assertion to an exception with a proper error message.