Plain Sockets Example ClientΒΆ

This example is a basic HTTP/2 client written using plain Python sockets, and ssl TLS/SSL wrapper for socket objects.

This client is not a complete production-ready HTTP/2 client and only intended as a demonstration sample.

This example shows the bare minimum that is needed to send an HTTP/2 request to a server, and read back a response body.

 1#!/usr/bin/env python3
 2
 3"""
 4plain_sockets_client.py
 5~~~~~~~~~~~~~~~~~~~~~~~
 6
 7Just enough code to send a GET request via h2 to an HTTP/2 server and receive a response body.
 8This is *not* a complete production-ready HTTP/2 client!
 9"""
10
11import socket
12import ssl
13import certifi
14
15import h2.connection
16import h2.events
17
18
19SERVER_NAME = 'http2.golang.org'
20SERVER_PORT = 443
21
22# generic socket and ssl configuration
23socket.setdefaulttimeout(15)
24ctx = ssl.create_default_context(cafile=certifi.where())
25ctx.set_alpn_protocols(['h2'])
26
27# open a socket to the server and initiate TLS/SSL
28s = socket.create_connection((SERVER_NAME, SERVER_PORT))
29s = ctx.wrap_socket(s, server_hostname=SERVER_NAME)
30
31c = h2.connection.H2Connection()
32c.initiate_connection()
33s.sendall(c.data_to_send())
34
35headers = [
36    (':method', 'GET'),
37    (':path', '/reqinfo'),
38    (':authority', SERVER_NAME),
39    (':scheme', 'https'),
40]
41c.send_headers(1, headers, end_stream=True)
42s.sendall(c.data_to_send())
43
44body = b''
45response_stream_ended = False
46while not response_stream_ended:
47    # read raw data from the socket
48    data = s.recv(65536 * 1024)
49    if not data:
50        break
51
52    # feed raw data into h2, and process resulting events
53    events = c.receive_data(data)
54    for event in events:
55        print(event)
56        if isinstance(event, h2.events.DataReceived):
57            # update flow control so the server doesn't starve us
58            c.acknowledge_received_data(event.flow_controlled_length, event.stream_id)
59            # more response body data received
60            body += event.data
61        if isinstance(event, h2.events.StreamEnded):
62            # response body completed, let's exit the loop
63            response_stream_ended = True
64            break
65    # send any pending data to the server
66    s.sendall(c.data_to_send())
67
68print("Response fully received:")
69print(body.decode())
70
71# tell the server we are closing the h2 connection
72c.close_connection()
73s.sendall(c.data_to_send())
74
75# close the socket
76s.close()