h2 is a Python library that provides a state-machine based implementation of the HTTP/2 protocol, allowing for low-level interaction with HTTP/2 connections. It is currently at version 5.0.11 and maintains a regular release cadence, often driven by performance improvements and updates to underlying Rust dependencies via `pyo3`.
pip install h2Verified import paths — ran on the pinned version, not inferred.
Initializes an HTTP/2 client connection, sends the connection preamble, and then sends a GET request with headers. It then explains the event-driven nature of `h2` for receiving and processing data, which requires explicit integration with a network I/O layer.
Refer to the `h2` documentation and changelog for v3.0 migration. Update header arguments to a list of `(name, value)` byte-string tuples. Review API calls for changed method signatures.
Implement explicit I/O loops that read data from the network, pass it to `H2Connection.receive_data()`, get output bytes from `H2Connection.data_to_send()`, and write them back to the network.
Implement a comprehensive event handling loop that iterates through all `h2.events.Event` objects. Ensure `acknowledge_received_data` is called for every `DataReceived` event and `data_to_send` is regularly invoked to push out flow control updates.
Always construct headers as `list[tuple[bytes, bytes]]` (or automatically encoded tuples if `header_encoding` is set) to maintain order and adhere to HTTP/2 specifications.
For flow control issues, ensure you check the available window using `conn.local_flow_control_window(stream_id)` before sending data and segment large data into smaller frames. For header issues, verify that your header lists adhere to RFC 7540 specifications, including correct pseudo-headers and avoiding forbidden connection-specific headers (like 'connection', 'keep-alive', 'transfer-encoding'). Example for checking flow control:
```python
import h2.connection
conn = h2.connection.H2Connection()
stream_id = conn.get_next_available_stream_id()
# ... (send headers, etc.)
data_to_send = b'some data'
max_send = conn.local_flow_control_window(stream_id)
if len(data_to_send) > max_send:
# Split data or wait for a WINDOW_UPDATE event
print(f'Cannot send all data. Available window: {max_send}')
else:
conn.send_data(stream_id, data_to_send)
```Implement robust state management for your HTTP/2 streams. After receiving `StreamEnded` or `StreamReset` events, avoid further operations on that specific `stream_id`. If interacting with a remote peer that sends frames (like `RST_STREAM` or `WINDOW_UPDATE`) on a stream that your `h2` connection has already marked as closed, consider gracefully ignoring these events in your event loop after the stream has transitioned to a terminal state.
Update your code to reference the setting constants through `h2.settings.SettingCodes`. For example, change `h2.settings.ENABLE_PUSH` to `h2.settings.SettingCodes.ENABLE_PUSH`. If you are using an external library that has this issue, you might need to upgrade that library to a version compatible with your `h2` installation, or temporarily pin your `h2` version to an older release (e.g., `pip install 'h2<3.0.0'`) if compatible updates are not available.
Ensure that your application respects the `SETTINGS_MAX_CONCURRENT_STREAMS` advertised by the remote peer. If you are acting as a client, you should not initiate more streams than the remote server allows. If you are acting as a server, you can configure your own `SETTINGS_MAX_CONCURRENT_STREAMS` and ensure client requests don't exceed it. When a stream is closed, its slot for concurrent streams becomes available again. Wait for streams to close before opening new ones if you are near the limit.
```python
import h2.connection
conn = h2.connection.H2Connection()
# ... process settings from remote peer ...
# Example: if remote_max_concurrent_streams is known from SETTINGS_MAX_CONCURRENT_STREAMS
# if conn.open_outbound_streams < remote_max_concurrent_streams:
# stream_id = conn.get_next_available_stream_id()
# conn.send_headers(stream_id, headers, end_stream=False)
# else:
# print('Too many concurrent streams, wait for one to close.')
```No dependency data recorded yet.