### Install hyperframe from source Source: https://github.com/python-hyper/hyperframe/blob/master/docs/source/installation.md Use this command to install hyperframe after downloading and extracting the release tarball from GitHub. ```console python setup.py install ``` -------------------------------- ### Usage Examples Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/goaway-frame.md Provides examples of how to use the GoAwayFrame for different scenarios, including graceful shutdown, shutdown with a reason, and protocol errors. ```APIDOC ## Usage Examples ### Graceful shutdown This example demonstrates creating a GOAWAY frame for a graceful connection shutdown without any specific error. ```python from hyperframe.frame import GoAwayFrame frame = GoAwayFrame() frame.last_stream_id = 50 # Last stream we processed frame.error_code = 0 # NO_ERROR (graceful) data = frame.serialize() ``` ### Shutdown with reason This example shows how to send a GOAWAY frame with a specific error code and additional data to provide a reason for the shutdown. ```python from hyperframe.frame import GoAwayFrame frame = GoAwayFrame() frame.last_stream_id = 100 frame.error_code = 0xB # ENHANCE_YOUR_CALM frame.additional_data = b'Too many requests, please reduce load' data = frame.serialize() ``` ### Protocol error This example illustrates sending a GOAWAY frame to indicate a protocol error during connection. ```python from hyperframe.frame import GoAwayFrame frame = GoAwayFrame() frame.last_stream_id = 5 frame.error_code = 0x1 # PROTOCOL_ERROR frame.additional_data = b'Invalid SETTINGS frame' data = frame.serialize() ``` ### Parsing GOAWAY This example demonstrates how to parse an incoming GOAWAY frame, extract its details, and interpret the error code and additional data. ```python from hyperframe.frame import Frame, GoAwayFrame # Assume receive_9_bytes() and receive_bytes() are defined elsewhere # header = receive_9_bytes() # frame, length = Frame.parse_frame_header(memoryview(header)) # if isinstance(frame, GoAwayFrame): # body = receive_bytes(length) # frame.parse_body(memoryview(body)) # error_codes = { # 0x0: "NO_ERROR", # 0x1: "PROTOCOL_ERROR", # 0x2: "INTERNAL_ERROR", # 0x3: "FLOW_CONTROL_ERROR", # 0xB: "ENHANCE_YOUR_CALM", # 0xC: "INADEQUATE_SECURITY", # } # error_name = error_codes.get(frame.error_code, f"UNKNOWN({frame.error_code})") # print(f"Connection closing: {error_name}") # if frame.additional_data: # print(f"Reason: {frame.additional_data.decode('utf-8', errors='ignore')}") # print(f"Last processed stream: {frame.last_stream_id}") ``` ### Handling outstanding streams This example shows how to handle a GOAWAY frame by identifying and managing streams that were outstanding when the connection was terminated. ```python from hyperframe.frame import Frame, GoAwayFrame # Assume active_streams is a list of active stream IDs # Assume data is the received bytes containing the GOAWAY frame # def handle_goaway(data): # frame, length = Frame.parse_frame_header(memoryview(data[:9])) # if isinstance(frame, GoAwayFrame): # body = data[9:9+length] # frame.parse_body(memoryview(body)) # # Streams > last_stream_id were never processed # # Retry them on another connection # unprocessed = [s for s in active_streams if s > frame.last_stream_id] # # Streams <= last_stream_id might have been processed # # Wait for completion or abort # maybe_processed = [s for s in active_streams if s <= frame.last_stream_id] ``` ``` -------------------------------- ### Usage Example: Receiving and validating promises Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Provides an example of how to receive, parse, and validate incoming PUSH_PROMISE frames, including checking the promised stream ID. ```APIDOC ## Usage Example: Receiving and validating promises ### Description Provides an example of how to receive, parse, and validate incoming PUSH_PROMISE frames, including checking the promised stream ID. ### Code ```python from hyperframe.frame import Frame, PushPromiseFrame def handle_push_promise(data): frame, length = Frame.parse_frame_header(memoryview(data[:9])) if isinstance(frame, PushPromiseFrame): body = data[9:9+length] frame.parse_body(memoryview(body)) # Validate promised stream ID (must be even for server-initiated) if frame.promised_stream_id % 2 != 0: raise ValueError("Invalid promised stream ID") # Extract and decode headers print(f"Server pushing stream {frame.promised_stream_id}") print(f"Header data: {frame.data.hex()}") ``` ``` -------------------------------- ### HEADERS with Priority Usage Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/headers-frame.md Example showing how to create a HEADERS frame with priority information, including dependency, weight, and exclusivity. ```APIDOC ## HEADERS with priority ### Description Example demonstrating the creation of a HEADERS frame with priority settings. ### Code ```python from hyperframe.frame import HeadersFrame frame = HeadersFrame(stream_id=3) frame.data = b'\x82' # Encoded header frame.flags.add('PRIORITY') frame.flags.add('END_HEADERS') frame.depends_on = 1 # Depends on stream 1 frame.stream_weight = 64 # Medium weight frame.exclusive = False serialized = frame.serialize() ``` ``` -------------------------------- ### Usage Example: Push a resource Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Demonstrates how to create and serialize a PushPromiseFrame to push a resource, such as a CSS file, on a specific stream. ```APIDOC ## Usage Example: Push a resource ### Description Demonstrates how to create and serialize a PushPromiseFrame to push a resource, such as a CSS file, on a specific stream. ### Code ```python from hyperframe.frame import PushPromiseFrame # Server pushes /style.css on stream 1 frame = PushPromiseFrame(stream_id=1) frame.promised_stream_id = 2 # Server-initiated stream (even) frame.data = b'\x87\x41\x0fwww.example.com\x1d/style.css' # GET /style.css frame.flags.add('END_HEADERS') data = frame.serialize() ``` ``` -------------------------------- ### Install hyperframe using pip Source: https://github.com/python-hyper/hyperframe/blob/master/docs/source/installation.md Use this command to install the hyperframe package from the Python Package Index. ```console pip install hyperframe ``` -------------------------------- ### Example: Serializing a GoAwayFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/goaway-frame.md Demonstrates how to create a GoAwayFrame, set its attributes (last_stream_id, error_code, additional_data), and then serialize it into bytes. ```python from hyperframe.frame import GoAwayFrame frame = GoAwayFrame() frame.last_stream_id = 100 frame.error_code = 0 # NO_ERROR frame.additional_data = b'Going away for maintenance' serialized = frame.serialize() ``` -------------------------------- ### Usage Example: Send PING request Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Example demonstrating how to create and serialize a PING frame, often used for sending a timestamp to measure round-trip time. ```APIDOC ## Usage Example: Send PING request ```python from hyperframe.frame import PingFrame import struct frame = PingFrame() # Send current timestamp for round-trip measurement import time timestamp = int(time.time() * 1000) # milliseconds frame.opaque_data = struct.pack('>Q', timestamp) data = frame.serialize() ``` ``` -------------------------------- ### Usage Example: Send PING ACK Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Example showing how to construct a PING ACK frame in response to a received PING frame, using the same opaque data. ```APIDOC ## Usage Example: Send PING ACK ```python from hyperframe.frame import PingFrame # Receiver responds with same data request_data = received_ping.opaque_data frame = PingFrame() frame.opaque_data = request_data frame.flags.add('ACK') data = frame.serialize() ``` ``` -------------------------------- ### Usage Example: Multiple continuations Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/continuation-frame.md Illustrates splitting a very large header block across multiple CONTINUATION frames. ```APIDOC ## Usage Example: Multiple continuations ### Description Demonstrates splitting a very large header block into an initial HEADERS frame followed by multiple CONTINUATION frames. ### Code ```python from hyperframe.frame import HeadersFrame, ContinuationFrame # Very large header block split into multiple frames header_chunks = [ b'\x82' * 16000, # 16KB b'\x86' * 16000, # 16KB b'\x84' * 4000, # 4KB ] # Initial HEADERS frame frame = HeadersFrame(stream_id=1) frame.data = header_chunks[0] send(frame.serialize()) # CONTINUATION frames for remaining chunks for chunk in header_chunks[1:-1]: frame = ContinuationFrame(stream_id=1) frame.data = chunk send(frame.serialize()) # Final CONTINUATION with END_HEADERS frame = ContinuationFrame(stream_id=1) frame.data = header_chunks[-1] frame.flags.add('END_HEADERS') send(frame.serialize()) ``` ``` -------------------------------- ### Usage Example: Advertise alternate protocol Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Demonstrates how to create and serialize an AltSvcFrame to advertise an alternative protocol for a specific stream. ```APIDOC ## Usage Example: Advertise alternate protocol ### Description Demonstrates how to create and serialize an AltSvcFrame to advertise an alternative protocol for a specific stream. ### Example ```python from hyperframe.frame import AltSvcFrame # Stream-specific: alternative for current origin frame = AltSvcFrame(stream_id=1) frame.origin = b'' # Empty for stream-specific frame.field = b'h3=":443"; ma=3600' # QUIC available serialized = frame.serialize() ``` ``` -------------------------------- ### Usage Example: Multiple protocols Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Shows how to advertise multiple alternative protocols within a single AltSvcFrame, including preferences and maximum age. ```APIDOC ## Usage Example: Multiple protocols ### Description Shows how to advertise multiple alternative protocols within a single AltSvcFrame, including preferences and maximum age. ### Example ```python from hyperframe.frame import AltSvcFrame # Advertise multiple alternates frame = AltSvcFrame(stream_id=0) frame.origin = b'cdn.example.com' # Multiple protocols with preferences and max-age frame.field = b'h3=":443"; h2=":443"; h1=":80"; ma=604800' serialized = frame.serialize() ``` ``` -------------------------------- ### Example: Serializing SettingsFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/settings-frame.md Demonstrates how to create a SettingsFrame, populate its settings attribute with predefined constants, and then serialize the entire frame. This is useful for sending initial connection configurations. ```python from hyperframe.frame import SettingsFrame frame = SettingsFrame() frame.settings = { SettingsFrame.HEADER_TABLE_SIZE: 4096, SettingsFrame.ENABLE_PUSH: 0, SettingsFrame.MAX_CONCURRENT_STREAMS: 128, } serialized = frame.serialize() ``` -------------------------------- ### Usage Example: Multiple pushes on same stream Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Illustrates how to send multiple PUSH_PROMISE frames for different resources initiated from the same stream. ```APIDOC ## Usage Example: Multiple pushes on same stream ### Description Illustrates how to send multiple PUSH_PROMISE frames for different resources initiated from the same stream. ### Code ```python from hyperframe.frame import PushPromiseFrame # Push multiple resources promises = [ (2, b'GET /style.css'), (4, b'GET /script.js'), (6, b'GET /image.png'), ] for promised_id, headers in promises: frame = PushPromiseFrame(stream_id=1) frame.promised_stream_id = promised_id frame.data = headers # Encoded headers frame.flags.add('END_HEADERS') send(frame.serialize()) ``` ``` -------------------------------- ### Serialize Padding Data Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/mixins.md Demonstrates how to serialize padding data using the serialize_padding_data method. It shows the output when the PADDED flag is set and when it is not. ```python from hyperframe.frame import DataFrame frame = DataFrame(1, data=b'test') frame.flags.add('PADDED') frame.pad_length = 10 padding_bytes = frame.serialize_padding_data() # Returns b'\x0A' (one byte with value 10) frame.flags.discard('PADDED') padding_bytes = frame.serialize_padding_data() # Returns b'' (empty) ``` -------------------------------- ### Full Padding Flow Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/mixins.md Demonstrates the complete padding flow, from creating a padded DataFrame with padding data to serialization and subsequent parsing upon receiving. ```python from hyperframe.frame import DataFrame # Create padded DATA frame frame = DataFrame(stream_id=1) frame.data = b'secret' frame.flags.add('PADDED') frame.pad_length = 20 # Add 20 bytes of padding # Serialize produces: [9-byte-header][1-byte-pad-length][data][20-zero-bytes] serialized = frame.serialize() # When receiving: recv_frame, length = Frame.parse_frame_header(memoryview(serialized[:9])) recv_frame.parse_body(memoryview(serialized[9:9+length])) assert recv_frame.data == b'secret' assert recv_frame.pad_length == 20 assert recv_frame.flow_controlled_length == 6 + 20 + 1 # 27 ``` -------------------------------- ### Example: Sending Initial Settings Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/settings-frame.md Shows how a server can advertise its connection parameters by creating a SettingsFrame, populating it with various settings, and then serializing it to bytes. This is typically done at the beginning of an HTTP/2 connection. ```python from hyperframe.frame import SettingsFrame # Server advertises settings frame = SettingsFrame() frame.settings = { SettingsFrame.HEADER_TABLE_SIZE: 4096, SettingsFrame.ENABLE_PUSH: 1, SettingsFrame.MAX_CONCURRENT_STREAMS: 100, SettingsFrame.INITIAL_WINDOW_SIZE: 65535, SettingsFrame.MAX_FRAME_SIZE: 16384, SettingsFrame.MAX_HEADER_LIST_SIZE: 8192, } data = frame.serialize() ``` -------------------------------- ### Usage Examples Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/rst-stream-frame.md Provides practical examples of how to use the RstStreamFrame class for various scenarios, including cancelling a stream, reporting protocol errors, graceful closure, and parsing reset frames. ```APIDOC ## Usage Examples ### Cancel a stream ```python from hyperframe.frame import RstStreamFrame # Client cancels the stream frame = RstStreamFrame(stream_id=1) frame.error_code = 0x8 # CANCEL data = frame.serialize() ``` ### Protocol error ```python from hyperframe.frame import RstStreamFrame # Peer violated protocol frame = RstStreamFrame(stream_id=3) frame.error_code = 0x1 # PROTOCOL_ERROR data = frame.serialize() ``` ### Graceful stream closure ```python from hyperframe.frame import RstStreamFrame # Close stream without error frame = RstStreamFrame(stream_id=5) frame.error_code = 0x0 # NO_ERROR data = frame.serialize() ``` ### Parsing reset frame ```python from hyperframe.frame import Frame, RstStreamFrame header = receive_9_bytes() frame, length = Frame.parse_frame_header(memoryview(header)) if isinstance(frame, RstStreamFrame): body = receive_bytes(length) frame.parse_body(memoryview(body)) error_names = { 0x0: "NO_ERROR", 0x1: "PROTOCOL_ERROR", 0x8: "CANCEL", } error_name = error_names.get(frame.error_code, "UNKNOWN") print(f"Stream {frame.stream_id} reset: {error_name}") ``` ``` -------------------------------- ### Usage Example: Padded push promise Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Shows how to create a PUSH_PROMISE frame with padding, obscuring the actual length of the promised data. ```APIDOC ## Usage Example: Padded push promise ### Description Shows how to create a PUSH_PROMISE frame with padding, obscuring the actual length of the promised data. ### Code ```python from hyperframe.frame import PushPromiseFrame frame = PushPromiseFrame(stream_id=1) frame.promised_stream_id = 2 frame.data = b'\x82' # Encoded header frame.flags.add('PADDED') frame.flags.add('END_HEADERS') frame.pad_length = 10 # Hide push length data = frame.serialize() ``` ``` -------------------------------- ### Usage Example: Basic header continuation Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/continuation-frame.md Demonstrates how to send a header block that is too large for a single frame using HEADERS and CONTINUATION frames. ```APIDOC ## Usage Example: Basic header continuation ### Description Shows how to handle header blocks exceeding the maximum frame size by splitting them across a HEADERS frame and a CONTINUATION frame. ### Code ```python from hyperframe.frame import HeadersFrame, ContinuationFrame # Header block is too large to fit in one frame headers_part1 = b'\x82\x86' * 8000 # ~16KB headers_part2 = b'\x84\x41' * 100 # ~200 bytes # First HEADERS frame (partial headers) frame1 = HeadersFrame(stream_id=1) frame1.data = headers_part1 # Don't set END_HEADERS yet # CONTINUATION frame with remaining headers frame2 = ContinuationFrame(stream_id=1) frame2.data = headers_part2 frame2.flags.add('END_HEADERS') send(frame1.serialize()) send(frame2.serialize()) ``` ``` -------------------------------- ### Example: Connection Shutdown with Reason Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/goaway-frame.md Demonstrates initiating a connection shutdown with a specific error code and additional debug data explaining the reason. This is useful for informing the peer about the cause of termination. ```python from hyperframe.frame import GoAwayFrame frame = GoAwayFrame() frame.last_stream_id = 100 frame.error_code = 0xB # ENHANCE_YOUR_CALM frame.additional_data = b'Too many requests, please reduce load' data = frame.serialize() ``` -------------------------------- ### Usage Example: Measuring round-trip Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md A comprehensive example illustrating the process of sending a PING frame with a timestamp and calculating the round-trip time upon receiving the PING ACK. ```APIDOC ## Usage Example: Measuring round-trip ```python from hyperframe.frame import Frame, PingFrame import time import struct # Send PING ping = PingFrame() timestamp = int(time.time() * 1000) ping.opaque_data = struct.pack('>Q', timestamp) send(ping.serialize()) # Receive PING response header = receive_9_bytes() frame, length = Frame.parse_frame_header(memoryview(header)) if isinstance(frame, PingFrame) and 'ACK' in frame.flags: body = receive_bytes(length) frame.parse_body(memoryview(body)) response_time = struct.unpack('>Q', frame.opaque_data)[0] rtt_ms = int(time.time() * 1000) - response_time print(f"Round-trip time: {rtt_ms}ms") ``` ``` -------------------------------- ### Create DataFrame with flags in constructor Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/flags.md Example of initializing a DataFrame with flags directly in the constructor. This is a concise way to set initial flags. ```python from hyperframe.frame import DataFrame, HeadersFrame # Method 1: Set flags in constructor frame = DataFrame(1, flags=['END_STREAM', 'PADDED']) ``` -------------------------------- ### Serialize PushPromiseFrame Body Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Demonstrates how to serialize a PushPromiseFrame, including setting the promised stream ID, header data, and flags. ```python from hyperframe.frame import PushPromiseFrame frame = PushPromiseFrame(1) frame.promised_stream_id = 2 frame.data = b'\x82' # Encoded GET frame.flags.add('END_HEADERS') serialized = frame.serialize() ``` -------------------------------- ### Example: Limiting Connections with Settings Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/settings-frame.md Shows how to use SettingsFrame to limit connection resources. By setting MAX_CONCURRENT_STREAMS and INITIAL_WINDOW_SIZE to lower values, the client or server can control the number of simultaneous streams and the memory used for flow control. ```python from hyperframe.frame import SettingsFrame frame = SettingsFrame() frame.settings = { SettingsFrame.MAX_CONCURRENT_STREAMS: 50, # Limit to 50 streams SettingsFrame.INITIAL_WINDOW_SIZE: 32768, # Smaller window to limit memory } data = frame.serialize() ``` -------------------------------- ### Multiple Pushes on Same Stream Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Shows how to send multiple push promises for different resources on the same initiating stream. Iterates through a list of promised IDs and headers, serializing each frame. ```python from hyperframe.frame import PushPromiseFrame # Push multiple resources promises = [ (2, b'GET /style.css'), (4, b'GET /script.js'), (6, b'GET /image.png'), ] for promised_id, headers in promises: frame = PushPromiseFrame(stream_id=1) frame.promised_stream_id = promised_id frame.data = headers # Encoded headers frame.flags.add('END_HEADERS') send(frame.serialize()) ``` -------------------------------- ### HEADERS with Exclusive Priority Usage Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/headers-frame.md Example illustrating the creation of a HEADERS frame with an exclusive priority dependency. ```APIDOC ## HEADERS with exclusive priority ### Description Example demonstrating the creation of a HEADERS frame with an exclusive priority dependency. ### Code ```python from hyperframe.frame import HeadersFrame frame = HeadersFrame(stream_id=7) frame.data = encoded_headers frame.flags.add('PRIORITY') frame.exclusive = True # Exclusive dependency frame.depends_on = 5 frame.stream_weight = 256 # Highest weight serialized = frame.serialize() ``` ``` -------------------------------- ### Stream Flow Control Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/window-update-frame.md Shows how to create a WINDOW_UPDATE frame to inform a peer that they can send more data on a specific stream. This is used for stream-level flow control. ```python from hyperframe.frame import WindowUpdateFrame # Tell peer they can send 64KB more data on stream 1 frame = WindowUpdateFrame(stream_id=1) frame.window_increment = 65536 data = frame.serialize() ``` -------------------------------- ### Basic HEADERS frame Usage Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/headers-frame.md Example demonstrating the creation and serialization of a basic HEADERS frame with encoded headers and the END_HEADERS flag. ```APIDOC ## Basic HEADERS frame ### Description Example demonstrating the creation and serialization of a basic HEADERS frame. ### Code ```python from hyperframe.frame import HeadersFrame # Create request HEADERS frame frame = HeadersFrame(stream_id=1) frame.data = b'\x82\x84\x86\x41\x0fwww.example.com' # Encoded headers frame.flags.add('END_HEADERS') serialized = frame.serialize() ``` ``` -------------------------------- ### Parse Priority Data Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/mixins.md Demonstrates parsing priority data from the beginning of a frame body, extracting stream dependency and weight information. ```python from hyperframe.frame import PriorityFrame frame = PriorityFrame(3) # Body: [depends_on=1, exclusive=1][stream_weight=64] ``` -------------------------------- ### Example: Connection Keep-Alive Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Generates a PING frame with empty opaque data, suitable for sending periodically to maintain an open connection. ```python from hyperframe.frame import PingFrame def keep_connection_alive(): frame = PingFrame() frame.opaque_data = b'\x00' * 8 # Empty ping return frame.serialize() # Send periodically to keep connection open ``` -------------------------------- ### Padded Push Promise Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Demonstrates creating a PUSH_PROMISE frame with padding. Sets the PADDED and END_HEADERS flags, and specifies a pad_length to obscure the actual header data length. ```python from hyperframe.frame import PushPromiseFrame frame = PushPromiseFrame(stream_id=1) frame.promised_stream_id = 2 frame.data = b'\x82' # Encoded header frame.flags.add('PADDED') frame.flags.add('END_HEADERS') frame.pad_length = 10 # Hide push length data = frame.serialize() ``` -------------------------------- ### Example: Send PING Request Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Constructs and serializes a PING frame with the current timestamp in milliseconds as opaque data for round-trip measurement. ```python from hyperframe.frame import PingFrame import struct frame = PingFrame() # Send current timestamp for round-trip measurement import time timestamp = int(time.time() * 1000) # milliseconds frame.opaque_data = struct.pack('>Q', timestamp) data = frame.serialize() ``` -------------------------------- ### Example: Sending ACK for Settings Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/settings-frame.md Demonstrates how to send an acknowledgment (ACK) for a received SETTINGS frame. This is done by creating a SettingsFrame and adding the 'ACK' flag to its flags attribute. The body of such a frame will be empty. ```python from hyperframe.frame import SettingsFrame # Acknowledge peer's settings frame = SettingsFrame() frame.flags.add('ACK') data = frame.serialize() # Body will be empty ``` -------------------------------- ### Advertise Alternate Protocol (Stream-Specific) Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Example of advertising an alternative protocol for a specific stream. The origin must be empty for stream-specific advertisements. ```python from hyperframe.frame import AltSvcFrame # Stream-specific: alternative for current origin frame = AltSvcFrame(stream_id=1) frame.origin = b'' # Empty for stream-specific frame.field = b'h3=":443"; ma=3600' # QUIC available serialized = frame.serialize() ``` -------------------------------- ### Usage Example: Connection-level alternate service Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Illustrates creating and serializing an AltSvcFrame for connection-level advertisement of an alternate service for a specific origin. ```APIDOC ## Usage Example: Connection-level alternate service ### Description Illustrates creating and serializing an AltSvcFrame for connection-level advertisement of an alternate service for a specific origin. ### Example ```python from hyperframe.frame import AltSvcFrame # Connection-level: alternative for specific origin frame = AltSvcFrame(stream_id=0) frame.origin = b'api.example.com:443' frame.field = b'h2=":8443"; h3=":443"; ma=2592000' serialized = frame.serialize() ``` ``` -------------------------------- ### Example: Measuring Round-Trip Time Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Demonstrates the full cycle of sending a PING frame with a timestamp, receiving the response, parsing it, and calculating the round-trip time in milliseconds. ```python from hyperframe.frame import Frame, PingFrame import time import struct # Send PING ping = PingFrame() timestamp = int(time.time() * 1000) ping.opaque_data = struct.pack('>Q', timestamp) send(ping.serialize()) # Receive PING response header = receive_9_bytes() frame, length = Frame.parse_frame_header(memoryview(header)) if isinstance(frame, PingFrame) and 'ACK' in frame.flags: body = receive_bytes(length) frame.parse_body(memoryview(body)) response_time = struct.unpack('>Q', frame.opaque_data)[0] rtt_ms = int(time.time() * 1000) - response_time print(f"Round-trip time: {rtt_ms}ms") ``` -------------------------------- ### Usage Example: Connection keep-alive Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Demonstrates sending a PING frame with empty opaque data periodically to maintain an active connection. ```APIDOC ## Usage Example: Connection keep-alive ```python from hyperframe.frame import PingFrame def keep_connection_alive(): frame = PingFrame() frame.opaque_data = b'\x00' * 8 # Empty ping return frame.serialize() # Send periodically to keep connection open ``` ``` -------------------------------- ### Distribute Clients to Alternate Endpoints Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Example function to serialize an AltSvcFrame for load balancing clients across multiple alternate endpoints. ```python from hyperframe.frame import AltSvcFrame def advertise_load_balanced_endpoints(): """Distribute clients to alternate endpoints.""" frame = AltSvcFrame(stream_id=0) frame.origin = b'api.example.com' endpoints = [ 'h2=":443"', 'h2="api2.example.com:443"', 'h2="api3.example.com:443"', 'h3=":443"', ] frame.field = ('; '.join(endpoints) + '; ma=3600').encode('utf-8') return frame.serialize() ``` -------------------------------- ### Example: Parsing Received Settings Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/settings-frame.md Illustrates the process of receiving and parsing an HTTP/2 SETTINGS frame. It first parses the frame header, checks if it's a SettingsFrame, and then handles both ACK frames and frames containing actual settings, printing specific settings like MAX_FRAME_SIZE. ```python from hyperframe.frame import Frame, SettingsFrame header = receive_9_bytes() frame, length = Frame.parse_frame_header(memoryview(header)) if isinstance(frame, SettingsFrame) and 'ACK' in frame.flags: # Peer acknowledged our settings pass elif isinstance(frame, SettingsFrame): # Parse the settings body = receive_bytes(length) frame.parse_body(memoryview(body)) for setting_id, value in frame.settings.items(): if setting_id == SettingsFrame.MAX_FRAME_SIZE: print(f"Peer max frame size: {value}") ``` -------------------------------- ### Push a Resource Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/push-promise-frame.md Illustrates how a server can push a resource, like a CSS file, to a client using the PushPromiseFrame. Sets the stream ID, promised stream ID, header data, and END_HEADERS flag. ```python from hyperframe.frame import PushPromiseFrame # Server pushes /style.css on stream 1 frame = PushPromiseFrame(stream_id=1) frame.promised_stream_id = 2 # Server-initiated stream (even) frame.data = b'\x87\x41\x0fwww.example.com\x1d/style.css' # GET /style.css frame.flags.add('END_HEADERS') data = frame.serialize() ``` -------------------------------- ### Usage Example: Rotating endpoints Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Demonstrates how to use AltSvcFrame to advertise rotating or load-balanced endpoints, distributing clients across different service locations. ```APIDOC ## Usage Example: Rotating endpoints ### Description Demonstrates how to use AltSvcFrame to advertise rotating or load-balanced endpoints, distributing clients across different service locations. ### Example ```python from hyperframe.frame import AltSvcFrame def advertise_load_balanced_endpoints(): """Distribute clients to alternate endpoints.""" frame = AltSvcFrame(stream_id=0) frame.origin = b'api.example.com' endpoints = [ 'h2=":443"', 'h2="api2.example.com:443"', 'h2="api3.example.com:443"', 'h3=":443"', ] frame.field = ('; '.join(endpoints) + '; ma=3600').encode('utf-8') return frame.serialize() ``` ``` -------------------------------- ### Example: Serialize RstStreamFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/rst-stream-frame.md Demonstrates how to create an RstStreamFrame, set an error code, and serialize it. The resulting serialized frame includes the header and the 4-byte error code. ```python from hyperframe.frame import RstStreamFrame frame = RstStreamFrame(1) frame.error_code = 1 # PROTOCOL_ERROR serialized = frame.serialize() # Always produces 9 (header) + 4 (error code) = 13 bytes ``` -------------------------------- ### Serialize Priority Data Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/mixins.md Shows how to serialize priority data into 5 bytes, including the exclusive flag, depends_on stream ID, and stream weight. ```python from hyperframe.frame import PriorityFrame frame = PriorityFrame(3) frame.depends_on = 1 frame.stream_weight = 64 frame.exclusive = False priority_bytes = frame.serialize_priority_data() # Returns 5 bytes with depends_on=1, weight=64, exclusive=0 ``` -------------------------------- ### Parse Padding Data Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/mixins.md Illustrates how to parse padding data from frame body using the parse_padding_data method. It shows how pad_length is extracted and the number of bytes consumed. ```python from hyperframe.frame import DataFrame frame = DataFrame(1) frame.flags.add('PADDED') # Body: [pad_length=5][data][padding] body = memoryview(b'\x05test\x00\x00\x00\x00\x00') consumed = frame.parse_padding_data(body) # consumed = 1 (read one byte) # frame.pad_length = 5 ``` -------------------------------- ### Example: PingFrame Serialization Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Demonstrates serializing a PingFrame with opaque data set to the current timestamp. The serialized output always includes the header and 8 bytes of data. ```python from hyperframe.frame import PingFrame import time frame = PingFrame() frame.opaque_data = int(time.time()).to_bytes(8, 'big') serialized = frame.serialize() # Always produces 9 (header) + 8 (data) = 17 bytes ``` -------------------------------- ### Connection Flow Control Example Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/window-update-frame.md Illustrates creating a WINDOW_UPDATE frame for connection-level flow control. Setting `stream_id=0` indicates that the window increment applies to the entire connection. ```python from hyperframe.frame import WindowUpdateFrame # Tell peer they can send more data on any stream frame = WindowUpdateFrame(stream_id=0) frame.window_increment = 1048576 # 1MB for the connection data = frame.serialize() ``` -------------------------------- ### Usage Example: Parsing alternate services Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Provides a function to handle incoming ALTSVC frames, parse their bodies, and extract information about advertised alternate services. ```APIDOC ## Usage Example: Parsing alternate services ### Description Provides a function to handle incoming ALTSVC frames, parse their bodies, and extract information about advertised alternate services. ### Example ```python from hyperframe.frame import Frame, AltSvcFrame def handle_altsvc(data): frame, length = Frame.parse_frame_header(memoryview(data[:9])) if isinstance(frame, AltSvcFrame): body = data[9:9+length] frame.parse_body(memoryview(body)) origin = frame.origin.decode('utf-8') altsvc = frame.field.decode('utf-8') if frame.stream_id == 0: print(f"Connection-level: {origin} -> {altsvc}") else: print(f"Stream {frame.stream_id}: {altsvc}") # Parse Alt-Svc field value # Example: h3=":443"; h2=":443"; ma=604800 parse_altsvc_field(altsvc) ``` ``` -------------------------------- ### Example: Send PING ACK Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/ping-frame.md Creates and serializes a PING ACK frame using the opaque data received from a PING request. The 'ACK' flag is added to the frame. ```python from hyperframe.frame import PingFrame # Receiver responds with same data request_data = received_ping.opaque_data frame = PingFrame() frame.opaque_data = request_data frame.flags.add('ACK') data = frame.serialize() ``` -------------------------------- ### Example: Graceful Connection Shutdown Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/goaway-frame.md Shows how to create a GoAwayFrame for a graceful shutdown with no error code, indicating that the connection is closing normally. The last processed stream ID is specified. ```python from hyperframe.frame import GoAwayFrame frame = GoAwayFrame() frame.last_stream_id = 50 # Last stream we processed frame.error_code = 0 # NO_ERROR (graceful) data = frame.serialize() ``` -------------------------------- ### Create an Exclusive Dependency Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/priority-frame.md This example demonstrates how to create a stream that exclusively depends on another. This ensures the new stream becomes the sole direct child of its parent, affecting prioritization. ```python from hyperframe.frame import PriorityFrame # Stream 7 exclusively depends on stream 3 # This makes it the only child of stream 3 frame = PriorityFrame(stream_id=7) frame.depends_on = 3 frame.exclusive = True frame.stream_weight = 200 data = frame.serialize() ``` -------------------------------- ### Example: Parsing a GOAWAY Frame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/goaway-frame.md Shows how to parse the header and body of a received GOAWAY frame. It identifies the frame type, extracts error codes and additional data, and prints human-readable information about the connection closure. ```python from hyperframe.frame import Frame, GoAwayFrame header = receive_9_bytes() frame, length = Frame.parse_frame_header(memoryview(header)) if isinstance(frame, GoAwayFrame): body = receive_bytes(length) frame.parse_body(memoryview(body)) error_codes = { 0x0: "NO_ERROR", 0x1: "PROTOCOL_ERROR", 0x2: "INTERNAL_ERROR", 0x3: "FLOW_CONTROL_ERROR", 0xB: "ENHANCE_YOUR_CALM", 0xC: "INADEQUATE_SECURITY", } error_name = error_codes.get(frame.error_code, f"UNKNOWN({frame.error_code})") print(f"Connection closing: {error_name}") if frame.additional_data: print(f"Reason: {frame.additional_data.decode('utf-8', errors='ignore')}") print(f"Last processed stream: {frame.last_stream_id}") ``` -------------------------------- ### Example: Handling Outstanding Streams after GOAWAY Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/goaway-frame.md Illustrates a strategy for handling streams after receiving a GOAWAY frame. It differentiates between streams that were processed (up to last_stream_id) and those that were not, suggesting retries for unprocessed streams on a new connection. ```python from hyperframe.frame import Frame, GoAwayFrame def handle_goaway(data): frame, length = Frame.parse_frame_header(memoryview(data[:9])) if isinstance(frame, GoAwayFrame): body = data[9:9+length] frame.parse_body(memoryview(body)) # Streams > last_stream_id were never processed # Retry them on another connection unprocessed = [s for s in active_streams if s > frame.last_stream_id] # Streams <= last_stream_id might have been processed # Wait for completion or abort maybe_processed = [s for s in active_streams if s <= frame.last_stream_id] ``` -------------------------------- ### Handle Protocol Error with RstStreamFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/rst-stream-frame.md Example of sending an RstStreamFrame to indicate a protocol error (0x1) from the peer. ```python from hyperframe.frame import RstStreamFrame # Peer violated protocol frame = RstStreamFrame(stream_id=3) frame.error_code = 0x1 # PROTOCOL_ERROR data = frame.serialize() ``` -------------------------------- ### Cancel a Stream with RstStreamFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/rst-stream-frame.md Example of cancelling a client-initiated stream using RstStreamFrame with the CANCEL error code (0x8). ```python from hyperframe.frame import RstStreamFrame # Client cancels the stream frame = RstStreamFrame(stream_id=1) frame.error_code = 0x8 # CANCEL data = frame.serialize() ``` -------------------------------- ### Create and Serialize SETTINGS Frame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/index.md Creates a SETTINGS frame and populates it with common HTTP/2 connection parameters before serializing it. ```python from hyperframe.frame import SettingsFrame # Create SETTINGS frame settings = SettingsFrame() settings.settings = { SettingsFrame.HEADER_TABLE_SIZE: 4096, SettingsFrame.ENABLE_PUSH: 0, SettingsFrame.MAX_CONCURRENT_STREAMS: 100, } bytes_to_send = settings.serialize() ``` -------------------------------- ### Create and use a Flag instance Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/flags.md Demonstrates how to instantiate a Flag object and access its name and bit value. Flags can also be accessed by index like a tuple. ```python from hyperframe.flags import Flag flag = Flag("END_STREAM", 0x01) print(flag.name) # "END_STREAM" print(flag.bit) # 1 print(flag[0]) # "END_STREAM" (tuple index) ``` -------------------------------- ### Connection-Level Alternate Service Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Example of advertising an alternate service at the connection level for a specific origin. The stream_id is set to 0. ```python from hyperframe.frame import AltSvcFrame # Connection-level: alternative for specific origin frame = AltSvcFrame(stream_id=0) frame.origin = b'api.example.com:443' frame.field = b'h2=":8443"; h3=":443"; ma=2592000' serialized = frame.serialize() ``` -------------------------------- ### Graceful Stream Closure with RstStreamFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/rst-stream-frame.md Example of closing a stream gracefully without any error using RstStreamFrame with the NO_ERROR code (0x0). ```python from hyperframe.frame import RstStreamFrame # Close stream without error frame = RstStreamFrame(stream_id=5) frame.error_code = 0x0 # NO_ERROR data = frame.serialize() ``` -------------------------------- ### Get the number of set flags in a DataFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/flags.md Shows how to retrieve the count of currently set flags on a DataFrame using the `len()` function. ```python from hyperframe.frame import DataFrame frame = DataFrame(1) print(len(frame.flags)) # 0 frame.flags.add('END_STREAM') print(len(frame.flags)) # 1 ``` -------------------------------- ### Creating Priority Frames Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/mixins.md Demonstrates creating PriorityFrame objects to represent stream dependencies and weights. Shows how to set stream ID, dependency, weight, and exclusivity. ```python from hyperframe.frame import PriorityFrame # Stream 3 depends on root (stream 0) frame1 = PriorityFrame(stream_id=3) frame1.depends_on = 0 # Stream 5 depends on stream 3 with weight frame2 = PriorityFrame(stream_id=5) frame2.depends_on = 3 frame2.stream_weight = 200 # High priority # Stream 7 exclusively depends on stream 3 frame3 = PriorityFrame(stream_id=7) frame3.depends_on = 3 frame3.exclusive = True # Makes it the only child # Resulting structure: # 0 (root) # └── 3 # ├── 7 (exclusive) # └── 5 (weight=200) ``` -------------------------------- ### Usage Example: Parsing fragmented headers Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/continuation-frame.md Provides a function to collect and parse a sequence of fragmented header frames until the END_HEADERS flag is encountered. ```APIDOC ## Usage Example: Parsing fragmented headers ### Description Includes functions to collect a series of HTTP/2 frames that constitute a fragmented header block and then decode the complete header data. ### Code ```python from hyperframe.frame import Frame, HeadersFrame, ContinuationFrame def collect_header_frames(data_stream): """Collect all frames until END_HEADERS.""" frames = [] while True: # Parse frame header header = data_stream.read(9) frame, length = Frame.parse_frame_header(memoryview(header)) # Parse frame body body = data_stream.read(length) frame.parse_body(memoryview(body)) frames.append(frame) # Check for END_HEADERS flag if 'END_HEADERS' in frame.flags: break # Must be HEADERS or CONTINUATION before END_HEADERS if not isinstance(frame, (HeadersFrame, ContinuationFrame)): raise ValueError("Expected HEADERS or CONTINUATION frame") return frames # Usage: def decode_header_block(data_stream): frames = collect_header_frames(data_stream) # Concatenate header data from all frames header_data = b''.join(f.data for f in frames) # Decode with HPACK decoder headers = hpack_decoder.decode(header_data) return headers ``` ``` -------------------------------- ### Creating Frames Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/index.md Illustrates the creation and serialization of DATA and SETTINGS frames. ```APIDOC ## Creating Frames ### Description This example demonstrates creating and serializing different types of HTTP/2 frames, such as DATA and SETTINGS frames, with their respective data and flags. ### Method ```python from hyperframe.frame import DataFrame, SettingsFrame # Create DATA frame data_frame = DataFrame(stream_id=1) data_frame.data = b'Hello, World!' data_frame.flags.add('END_STREAM') bytes_to_send = data_frame.serialize() # Create SETTINGS frame settings = SettingsFrame() settings.settings = { SettingsFrame.HEADER_TABLE_SIZE: 4096, SettingsFrame.ENABLE_PUSH: 0, SettingsFrame.MAX_CONCURRENT_STREAMS: 100, } bytes_to_send = settings.serialize() ``` ### Parameters - `stream_id` (int): The ID of the stream for the frame (for stream-level frames). - `data` (bytes): The payload data for the frame (for DATA frames). - `flags` (set): A set of flags to apply to the frame. - `settings` (dict): A dictionary of settings for the SETTINGS frame. ``` -------------------------------- ### Configure Custom Frame Size in SettingsFrame Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/configuration.md Demonstrates how to set a custom maximum frame size in a SettingsFrame, ensuring it does not exceed the absolute protocol limit before being applied. ```python from hyperframe.frame import SettingsFrame, FRAME_MAX_LEN, FRAME_MAX_ALLOWED_LEN # Server advertises custom frame size settings = SettingsFrame() custom_size = 32768 # 32KB # Validate before setting if custom_size > FRAME_MAX_ALLOWED_LEN: custom_size = FRAME_MAX_ALLOWED_LEN settings.settings[SettingsFrame.MAX_FRAME_SIZE] = custom_size ``` -------------------------------- ### Creating and handling custom protocol extensions Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/extension-frame.md Shows how to use `ExtensionFrame` to implement custom protocol extensions by defining a custom frame type and using `ExtensionFrame` to create, serialize, and parse these custom frames. ```APIDOC ## Custom protocol extensions ### Description This example demonstrates how to leverage `ExtensionFrame` for custom protocol extensions within HTTP/2. It defines a custom frame type, creates an `ExtensionFrame` with specific flags and data, serializes it, and then parses it back to verify its contents, showcasing a complete cycle for custom frame handling. ### Code Example ```python from hyperframe.frame import ExtensionFrame, Frame # Define a custom frame type for application protocol CUSTOM_TYPE = 0x20 CUSTOM_FLAG_DATA = 0x01 CUSTOM_FLAG_FINAL = 0x02 def create_custom_frame(stream_id, data): frame = ExtensionFrame( type=CUSTOM_TYPE, stream_id=stream_id, flag_byte=CUSTOM_FLAG_DATA | CUSTOM_FLAG_FINAL, body=data ) return frame # Create and serialize custom = create_custom_frame(1, b'custom payload') serialized = custom.serialize() # Parse and verify recv_header = serialized[:9] recv_frame, recv_length = Frame.parse_frame_header(memoryview(recv_header)) recv_frame.parse_body(memoryview(serialized[9:9+recv_length])) assert recv_frame.type == CUSTOM_TYPE assert recv_frame.flag_byte == (CUSTOM_FLAG_DATA | CUSTOM_FLAG_FINAL) assert recv_frame.body == b'custom payload' ``` ``` -------------------------------- ### AltSvcFrame Constructor Source: https://github.com/python-hyper/hyperframe/blob/master/_autodocs/api-reference/altsvc-frame.md Illustrates the initialization of an AltSvcFrame. The origin parameter is crucial for specifying the scope of the advertisement. ```python from hyperframe.frame import AltSvcFrame frame = AltSvcFrame(0) # Connection-level frame.origin = b"example.com" frame.field = b'h2=":443"; ma=3600' serialized = frame.serialize() ```