NAME
Net::HTTP2::nghttp2::Session - HTTP/2 session management
SYNOPSIS
use Net::HTTP2::nghttp2::Session;
my $session = Net::HTTP2::nghttp2::Session->new_server(
callbacks => {
on_begin_headers => sub {
my ($session, $stream_id) = @_;
# New stream started
},
on_header => sub {
my ($session, $stream_id, $name, $value, $flags) = @_;
# Header received
},
on_frame_recv => sub {
my ($session, $frame) = @_;
# Frame received
},
on_stream_close => sub {
my ($session, $stream_id, $error_code) = @_;
# Stream closed
},
on_data_chunk_recv => sub {
my ($session, $stream_id, $data, $flags) = @_;
# Body data received
},
},
);
# Send connection preface
$session->send_connection_preface(
max_concurrent_streams => 100,
);
# Process incoming data
$session->mem_recv($incoming_bytes);
# Get outgoing data to send
my $outgoing = $session->mem_send();
# Submit a response
$session->submit_response($stream_id,
status => 200,
headers => [
['content-type', 'text/html'],
],
body => '<html>...</html>',
);
METHODS
new_server
my $session = Net::HTTP2::nghttp2::Session->new_server(%args);
Create a new server-side HTTP/2 session.
Arguments:
- callbacks
-
Hashref of callback handlers. Required callbacks:
on_begin_headers,on_header,on_frame_recv. Optional:on_data_chunk_recv,on_stream_close. - user_data
-
Optional scalar passed to callbacks.
- settings
-
Optional hashref of initial HTTP/2 settings.
- stream_reset_burst / stream_reset_rate
-
Configure the incoming-
RST_STREAMrate limit (nghttp2's HTTP/2 Rapid Reset, CVE-2023-44487, mitigation). Both must be given together. They map tonghttp2_option_set_stream_reset_rate_limit(option, burst, rate): a token bucket ofbursttokens refilling atratetokens/second, one token per incomingRST_STREAM. When the bucket is empty nghttp2 sends GOAWAY and tears down the connection. Omit both to use nghttp2's own defaults (burst 1000, rate 33). Requires nghttp2 >= 1.57.
new_client
my $session = Net::HTTP2::nghttp2::Session->new_client(%args);
Create a new client-side HTTP/2 session.
Arguments:
- callbacks
-
Hashref of callback handlers. Recommended:
on_header,on_data_chunk_recv,on_stream_close. - user_data
-
Optional scalar passed to callbacks.
send_connection_preface
$session->send_connection_preface(%settings);
Send HTTP/2 connection preface (SETTINGS frame). Default settings: max_concurrent_streams => 100, initial_window_size => 65535.
Additional settings:
- enable_connect_protocol
-
Set to 1 to advertise RFC 8441 extended CONNECT support (
SETTINGS_ENABLE_CONNECT_PROTOCOL). Required for WebSocket over HTTP/2.
mem_recv
my $consumed = $session->mem_recv($data);
Feed incoming data to the session. Returns number of bytes consumed. Triggers registered callbacks as frames are parsed.
mem_send
my $data = $session->mem_send();
Get outgoing data from the session. Returns bytes to send to peer (empty string if nothing pending).
submit_request
my $stream_id = $session->submit_request(%args);
Submit an HTTP/2 request (client-side). Returns the stream ID.
Arguments:
- method
-
HTTP method. Default:
'GET'. - path
-
Request path. Default:
'/'. - scheme
-
URL scheme. Default:
'https'. -
Host authority (e.g.
'example.com'). - headers
-
Arrayref of
[$name, $value]pairs for additional headers (including pseudo-headers like:protocolfor RFC 8441 extended CONNECT). - body
-
Request body. Can be:
undef(or omitted)-
No body. HEADERS frame sent with END_STREAM.
- String
-
Static body. Sent as DATA frame(s) with END_STREAM after the last frame.
- CODE ref
-
Streaming callback for bidirectional streams. The callback receives
($stream_id, $max_length)and must return one of:($data, $eof_flag)-
Send data. A true EOF ends the stream, preserving pre-0.009 behavior.
($data, $eof_flag, $no_end_stream)-
Send data. When both flags are true, content production is complete but DATA does not carry END_STREAM, allowing
submit_trailer()to queue the terminal HEADERS block. The third value has no effect unless EOF is true. undefor an empty list-
Defer production until the stream is resumed or
submit_data()is called.
This is required for protocols that keep the stream open for bidirectional exchange, such as WebSocket over HTTP/2 (RFC 8441 extended CONNECT).
submit_response
$session->submit_response($stream_id, %args);
Submit an HTTP/2 response on the given stream.
Arguments:
- status
-
HTTP status code. Default:
200. - headers
-
Arrayref of
[$name, $value]pairs. - body
-
Response body. Same types as
submit_request:undef(no body), string (static body), or CODE ref (streaming callback).undef(or omitted)-
No body. HEADERS frame sent with END_STREAM.
- String
-
Static body. Sent as DATA frame(s) with END_STREAM after the last frame.
- CODE ref
-
Streaming callback. It receives
($stream_id, $max_length), or($stream_id, $max_length, $user_data)whencallback_datais defined, and must return one of:($data, $eof_flag)-
Send data. A true EOF ends the stream, preserving pre-0.009 behavior.
($data, $eof_flag, $no_end_stream)-
Send data. When both flags are true, content production is complete but DATA does not carry END_STREAM, allowing
submit_trailer()to queue the terminal HEADERS block. The third value has no effect unless EOF is true. undefor an empty list-
Defer production until the stream is resumed or
submit_data()is called.
- data_callback
-
Alternative to passing a CODE ref as
body. Callback with the same streaming signature. - callback_data
-
Optional user data passed as third argument to the streaming callback.
submit_trailer
$session->submit_trailer(
$stream_id,
headers => [
['x-checksum', 'abc'],
['set-cookie', 'a=1'],
['set-cookie', 'b=2'],
],
);
Queue a trailing HEADERS block that ends the stream. headers defaults to an empty array reference; order and duplicate names are preserved. Trailer names must be ordinary field names, not pseudo-header names beginning with :.
When trailers follow, the data provider must ultimately report EOF together with NO_END_STREAM, using ($data, 1, 1) or submit_data($stream_id, $data, 1, 1), so the final DATA does not consume END_STREAM. submit_trailer may be called inside the data callback or after that callback returns. Callers that do not send trailers should use the legacy two-value ($data, $eof_flag) callback or three-argument submit_data($stream_id, $data, $eof) form, where a true EOF retains the normal DATA END_STREAM behavior. An empty headers list queues an empty terminal HEADERS block.
A zero return means nghttp2 accepted the trailer block into its outbound queue. It does not mean the peer has received it. Invalid Perl input and immediate nghttp2 submission errors throw exceptions.
submit_push_promise
my $promised_stream_id = $session->submit_push_promise($stream_id, %args);
Submit a server push promise.
submit_data
$session->submit_data($stream_id, $data, $eof, $no_end_stream);
Push data directly onto an existing stream. The stream must already have a data provider (established by submit_request or submit_response with a CODE ref or data_callback). This replaces the streaming callback with a one-shot static body, then resumes the stream.
Arguments:
$stream_id-
The stream to send data on.
$data-
The data to send. Can be
undeffor an empty DATA frame. $eof-
If true, the DATA frame will include END_STREAM, closing the stream.
$no_end_stream-
Optional and false by default. When true together with a true
$eof, content production is complete but DATA does not include END_STREAM, allowingsubmit_trailer()to queue the terminal HEADERS block. It has no effect unless$eofis true. The three-argument form retains its existing behavior: a true$eofends the stream on DATA.
This is useful when you have data available outside the streaming callback context and want to push it directly, such as forwarding WebSocket frames received from another source.
resume_stream
$session->resume_stream($stream_id);
Resume data production for a deferred stream. Call this after a streaming body callback has returned undef and new data is available. Works for both request and response streams.
terminate_session
$session->terminate_session($error_code);
Send a GOAWAY frame and terminate the session. The $error_code should be an HTTP/2 wire error code (0 for NGHTTP2_NO_ERROR).
submit_rst_stream
$session->submit_rst_stream($stream_id, $error_code);
Send a RST_STREAM frame to abnormally terminate a stream. The $error_code should be an HTTP/2 error code (e.g. 0 for NO_ERROR, 8 for CANCEL).
submit_ping
$session->submit_ping($ack, $opaque_data);
Send a PING frame. Set $ack to 1 for a PING ACK response, 0 for an unsolicited PING. $opaque_data must be exactly 8 bytes, or undef for default.
submit_window_update
$session->submit_window_update($stream_id, $window_size_increment);
Send a WINDOW_UPDATE frame to increase the flow control window. Use $stream_id = 0 for connection-level flow control, or a specific stream ID for stream-level.
get_stream_user_data
my $data = $session->get_stream_user_data($stream_id);
Retrieve user data associated with a stream. Returns undef if no data is set.
set_stream_user_data
$session->set_stream_user_data($stream_id, $data);
Associate arbitrary user data with a stream. Useful for storing per-stream application state.
is_stream_deferred
my $bool = $session->is_stream_deferred($stream_id);
Returns true if the stream's data provider has been deferred (i.e. the streaming callback returned undef). The stream can be resumed with resume_stream().
want_read
my $bool = $session->want_read();
Returns true if the session wants to read more data.
want_write
my $bool = $session->want_write();
Returns true if the session has data to write.
resume_data
$session->resume_data($stream_id);
Low-level resume for deferred data production. Prefer resume_stream() which also clears the internal deferred flag.
CALLBACKS
All callbacks receive positional arguments and should return 0 on success.
on_begin_headers
sub { my ($stream_id, $frame_type, $flags) = @_; return 0; }
Called when a new headers block begins (new stream or trailers).
on_header
sub { my ($stream_id, $name, $value, $flags) = @_; return 0; }
Called for each header. Pseudo-headers (:method, :path, :scheme, :authority, :status, :protocol) are delivered before regular headers.
on_frame_recv
sub { my ($frame_hashref) = @_; return 0; }
Called when a complete frame is received. The hashref contains: type, flags, stream_id, length. A HEADERS frame additionally contains headers_category, one of:
NGHTTP2_HCAT_REQUEST-
Initial request headers.
NGHTTP2_HCAT_RESPONSE-
Initial response headers.
NGHTTP2_HCAT_PUSH_RESPONSE-
Pushed response headers.
NGHTTP2_HCAT_HEADERS-
A later ordinary HEADERS block on an open stream.
NGHTTP2_HCAT_HEADERS is not a universal is_trailer boolean: informational responses and message direction/state remain relevant when interpreting a later headers block.
on_data_chunk_recv
sub { my ($stream_id, $data, $flags) = @_; return 0; }
Called when body data is received on a stream.
on_stream_close
sub { my ($stream_id, $error_code) = @_; return 0; }
Called when a stream is closed.