Skip to content

Instantly share code, notes, and snippets.

@hkwi
Created March 11, 2017 17:06
Show Gist options
  • Save hkwi/4b3d4ea8b3982155fd998931a6d282bc to your computer and use it in GitHub Desktop.
Save hkwi/4b3d4ea8b3982155fd998931a6d282bc to your computer and use it in GitHub Desktop.
h2c server-push server example
import h11
import h2.events
import h2.connection
import eventlet
def handle(sock, addr):
con = h11.Connection(our_role=h11.SERVER)
con2 = h2.connection.H2Connection(client_side=False)
while True:
data = sock.recv(8192)
con.receive_data(data)
ev = con.next_event()
if ev == h11.NEED_DATA:
continue
elif isinstance(ev, h11.ConnectionClosed):
return
elif isinstance(ev, h11.Request):
break
else:
print("Unexpected", ev)
parent_id = 1
if ev.target == b"*" and ev.method == b"PRI":
con2.initiate_connection()
sock.send(con2.data_to_send())
for ev in con2.receive_data(data):
if isinstance(ev, h2.events.RequestReceived):
hd = dict(ev.headers)
if hd[":path"]=="/pushing" and hd[":method"]=="GET":
parent_id = ev.stream_id
con2.send_headers(parent_id, headers=[(":status","200")])
sock.send(con2.data_to_send())
break
else:
print(ev)
elif ev.target.split(b"?")[0] == b"/pushing" and ev.method==b"GET":
data = (b"HTTP/1.1 101 Switching Protocols\r\n" +
b"Connection: Upgrade\r\n" +
b"Upgrade: h2c\r\n" +
b"\r\n")
sock.send(data)
con2.initiate_upgrade_connection(dict(ev.headers)[b"http2-settings"])
con2.receive_data(con.trailing_data[0])
con2.send_headers(1, headers=[(b":status",b"200"),])
sock.send(con2.data_to_send())
else:
data = con.send(h11.Response(status_code=404, headers=[]))
data += con.send(h11.EndOfMessage())
sock.send(data)
return
def pusher():
i = 1
while True:
con2.push_stream(parent_id, i*2, [
(b":authority",b"localhost"),
(b":method",b"GET"),
(b":scheme",b"http"),
(b":path",("/push/%d" % i).encode("UTF-8")])
con2.send_headers(i*2, [
(b":status",b"200")],
end_stream=True)
sock.send(con2.data_to_send())
eventlet.sleep(2)
i += 1
eventlet.spawn(pusher)
while True:
sock.send(con2.data_to_send())
data = sock.recv(8192)
if len(data) == 0:
return
for ev in con2.receive_data(data):
print(ev)
addr = "localhost", 8080
eventlet.serve(eventlet.listen(addr), handle)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment