Last active
November 6, 2022 15:37
-
-
Save hkwi/728b15f88211a6e831d4292180d814a1 to your computer and use it in GitHub Desktop.
h2c server-push client example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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