Skip to content

Instantly share code, notes, and snippets.

@hkwi
Last active November 6, 2022 15:37
Show Gist options
  • Save hkwi/728b15f88211a6e831d4292180d814a1 to your computer and use it in GitHub Desktop.
Save hkwi/728b15f88211a6e831d4292180d814a1 to your computer and use it in GitHub Desktop.
h2c server-push client example
import re
import struct
import curio
import curio.socket as socket
import h11
import h2.connection
from urllib.parse import urlparse
async def push_test(url, callback):
pc = urlparse(url)
target = pc.path
if pc.query:
target += "?" + pc.query
addr = (pc.netloc, 80)
nc = re.match(r"(.*):(\d+)", pc.netloc)
if nc:
addr = (nc.group(1), int(nc.group(2)))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
con = h11.Connection(our_role=h11.CLIENT)
con2 = h2.connection.H2Connection()
await sock.connect(addr)
async with sock:
s = con.send(h11.Request(method="GET",
target=target,
headers=[("Host", "localhost"),
("Connection", "Upgrade, HTTP2-Settings"),
("Upgrade", "h2c"),
("HTTP2-Settings", con2.initiate_upgrade_connection())]))
s += con.send(h11.EndOfMessage())
await sock.send(s)
while True:
d = await sock.recv(8192)
if len(d):
con.receive_data(d)
else:
break
ev = con.next_event()
if isinstance(ev, h11.InformationalResponse):
break
elif ev is h11.NEED_DATA:
continue
else:
raise Exception("unexpected event")
# Switched to HTTP2
connected = True
await sock.send(con2.data_to_send())
data = con.trailing_data[0]
async def pinger():
i = 0
while connected:
con2.ping(struct.pack("!Q", i))
await sock.send(con2.data_to_send())
await curio.sleep(2)
i += 1
await curio.spawn(pinger())
while True:
for ev in con2.receive_data(data):
callback(ev)
data = await sock.recv(8192)
if len(data) == 0:
break
connected = False
curio.run(push_test("http://localhost:8080/pushing", print))
import re
import struct
import eventlet
import h11
import h2.connection
try:
from urllib.parse import urlparse
except:
from urlparse import urlparse
def push_test(url, callback):
pc = urlparse(url)
target = pc.path
if pc.query:
target += "?" + pc.query
addr = (pc.netloc, 80)
nc = re.match(r"(.*):(\d+)", pc.netloc)
if nc:
addr = (nc.group(1), int(nc.group(2)))
sock = eventlet.connect(addr)
con = h11.Connection(our_role=h11.CLIENT)
con2 = h2.connection.H2Connection()
s = con.send(h11.Request(method="GET",
target=target,
headers=[("Host", "localhost"),
("Connection", "Upgrade, HTTP2-Settings"),
("Upgrade", "h2c"),
("HTTP2-Settings", con2.initiate_upgrade_connection())]))
s += con.send(h11.EndOfMessage())
sock.send(s)
while True:
d = sock.recv(8192)
if len(d):
con.receive_data(d)
else:
return # EOF
ev = con.next_event()
if isinstance(ev, h11.InformationalResponse):
break
elif ev is h11.NEED_DATA:
continue
else:
return # Unexpected event
# Switched to HTTP2
connected = True
sock.send(con2.data_to_send())
data = con.trailing_data[0]
def pinger():
i = 0
while connected:
con2.ping(struct.pack("!Q", i))
sock.send(con2.data_to_send())
eventlet.sleep(2)
i += 1
eventlet.spawn(pinger)
while True:
for ev in con2.receive_data(data):
callback(ev)
data = sock.recv(8192)
if len(data) == 0:
break
connected = False
push_test("http://localhost:8080/pushing", print)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment