### Start h3 Client Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Run the example client to send an HTTP request to the server. Ensure the server is running before executing this command. ```bash > cargo run --example client -- https://localhost:4433 ``` -------------------------------- ### Start h3 Server Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Run the example server to listen on a specific address and port. This command also generates a self-signed certificate for encryption. ```bash > cargo run --example server -- --listen=127.0.0.1:4433 ``` -------------------------------- ### Add Content to h3 Server Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Start the server and specify a directory to serve content from. This allows the server to respond with files from the given directory. ```bash > cargo run --example server -- --listen=127.0.0.1:4433 --dir=content/root ``` -------------------------------- ### Quinn Server Setup for h3 Source: https://context7.com/hyperium/h3/llms.txt Sets up a TLS server configuration, creates a Quinn endpoint, and accepts incoming connections. Requires certificate and key files. ```rust use h3_quinn::{Connection, quinn}; use bytes::Bytes; use std::sync::Arc; // Server setup with Quinn async fn quinn_server_example() -> Result<(), Box> { let cert = rustls::pki_types::CertificateDer::from(std::fs::read("cert.der")?); let key = rustls::pki_types::PrivateKeyDer::try_from(std::fs::read("key.der")?)?; let mut tls_config = rustls::ServerConfig::builder() .with_no_client_auth() .with_single_cert(vec![cert], key)?; tls_config.max_early_data_size = u32::MAX; // Enable 0-RTT tls_config.alpn_protocols = vec![b"h3".to_vec()]; let server_config = quinn::ServerConfig::with_crypto(Arc::new( quinn::crypto::rustls::QuicServerConfig::try_from(tls_config)?, )); let endpoint = quinn::Endpoint::server(server_config, "[::]:4433".parse()?) ;?; while let Some(incoming) = endpoint.accept().await { tokio::spawn(async move { let conn = incoming.await.unwrap(); let h3_conn = h3::server::Connection::new( Connection::new(conn) ).await.unwrap(); // Handle requests... }); } Ok(()) } ``` -------------------------------- ### Create HTTP/3 Server Connection Source: https://context7.com/hyperium/h3/llms.txt Set up an HTTP/3 server using the h3 library and quinn. This example demonstrates TLS configuration, accepting incoming QUIC connections, and handling HTTP/3 requests. ```rust use h3::server::Connection; use h3_quinn::quinn; use bytes::Bytes; use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), Box> { // Setup TLS let cert = rustls::pki_types::CertificateDer::from(std::fs::read("server.cert")?); let key = rustls::pki_types::PrivateKeyDer::try_from(std::fs::read("server.key")?)?; let mut tls_config = rustls::ServerConfig::builder() .with_no_client_auth() .with_single_cert(vec![cert], key)?; tls_config.alpn_protocols = vec![b"h3".to_vec()]; let server_config = quinn::ServerConfig::with_crypto(Arc::new( quinn::crypto::rustls::QuicServerConfig::try_from(tls_config)?, )); let endpoint = quinn::Endpoint::server(server_config, "[::]:4433".parse()?)?; println!("Server listening on port 4433"); // Accept incoming connections while let Some(incoming) = endpoint.accept().await { tokio::spawn(async move { if let Ok(conn) = incoming.await { // Create HTTP/3 server connection let mut h3_conn = Connection::new(h3_quinn::Connection::new(conn)) .await .unwrap(); // Accept and handle requests while let Ok(Some(resolver)) = h3_conn.accept().await { tokio::spawn(async move { let (req, mut stream) = resolver.resolve_request().await.unwrap(); println!("Request: {} {}", req.method(), req.uri()); // Send response let response = http::Response::builder() .status(200) .body(()) .unwrap(); stream.send_response(response).await.unwrap(); stream.send_data(Bytes::from("Hello, HTTP/3!")).await.unwrap(); stream.finish().await.unwrap(); }); } } }); } Ok(()) } ``` -------------------------------- ### Quinn Client Setup for h3 Source: https://context7.com/hyperium/h3/llms.txt Configures TLS, creates a Quinn endpoint, and connects to an h3 server. Requires rustls and rustls-native-certs for TLS configuration. ```rust use h3_quinn::{Connection, quinn}; use bytes::Bytes; use std::sync::Arc; // Client setup with Quinn async fn quinn_client_example() -> Result<(), Box> { // Configure TLS let mut roots = rustls::RootCertStore::empty(); roots.add_parsable_certificates(rustls_native_certs::load_native_certs()?.certs); let mut tls_config = rustls::ClientConfig::builder() .with_root_certificates(roots) .with_no_client_auth(); tls_config.alpn_protocols = vec![b"h3".to_vec()]; // Create Quinn endpoint let mut endpoint = quinn::Endpoint::client("[::]:0".parse()?) ;?; let client_config = quinn::ClientConfig::new(Arc::new( quinn::crypto::rustls::QuicClientConfig::try_from(tls_config)?, )); endpoint.set_default_client_config(client_config); // Connect to server let addr = "127.0.0.1:4433".parse()?; let quinn_conn = endpoint.connect(addr, "localhost")?.await?; // Wrap in h3-quinn Connection let h3_quinn_conn = Connection::new(quinn_conn); // Create h3 client let (driver, send_request) = h3::client::new(h3_quinn_conn).await?; Ok(()) } ``` -------------------------------- ### Enable SSLKEYLOGFILE for h3 Client Debugging Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Configure the example client to generate an SSLKEYLOGFILE for unencrypted traffic analysis in tools like Wireshark. Set the environment variable and use the --keylogfile=true option. ```bash > export SSLKEYLOGFILE=./sslkeylog.log > cargo run --example client -- --keylogfile=true ``` -------------------------------- ### Configure h3 Server for Browser Testing Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Run the server configured for browser compatibility, listening on IPv6 and using specified certificate and key files. This setup is necessary for browsers to connect. ```bash > cargo run --example server -- --listen=[::]:4433 --dir=examples/root --cert=examples/cert.der --key=examples/key.der ``` -------------------------------- ### Access Specific File via h3 Client Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Start the client and specify a file name in the URI to request a specific file from the server. This requires the server to be running with content served. ```bash > cargo run --example client -- https://localhost:4433/index.html ``` -------------------------------- ### Create HTTP/3 Client Connection Source: https://context7.com/hyperium/h3/llms.txt Establishes a new HTTP/3 client connection from an existing QUIC connection. Requires QUIC endpoint setup and TLS configuration with ALPN for 'h3'. The connection driver and request sender are returned for concurrent use. ```rust use bytes::Bytes; use h3_quinn::quinn; use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), Box> { // Setup QUIC client endpoint let mut roots = rustls::RootCertStore::empty(); // Add certificates... let mut tls_config = rustls::ClientConfig::builder() .with_root_certificates(roots) .with_no_client_auth(); tls_config.alpn_protocols = vec![b"h3".to_vec()]; let client_endpoint = quinn::Endpoint::client("[::]:0".parse().unwrap())?; let client_config = quinn::ClientConfig::new(Arc::new( quinn::crypto::rustls::QuicClientConfig::try_from(tls_config)?, )); // Establish QUIC connection let conn = client_endpoint.connect(addr, "example.com")?.await?; let quinn_conn = h3_quinn::Connection::new(conn); // Create HTTP/3 client (returns driver and request sender) let (mut driver, mut send_request) = h3::client::new(quinn_conn).await?; // Drive the connection in background tokio::spawn(async move { futures::future::poll_fn(|cx| driver.poll_close(cx)).await; }); Ok(()) } ``` -------------------------------- ### Build HTTP/3 Server with Custom Settings Source: https://context7.com/hyperium/h3/llms.txt Configure server-specific settings including WebTransport and datagram support. Ensure necessary imports are present. ```rust use h3::server; use bytes::Bytes; async fn create_server_with_settings( quic_conn: C, ) -> Result, h3::error::ConnectionError> where C: h3::quic::Connection, { let connection = server::builder() .max_field_section_size(16384) // Max header size .send_grease(true) // Enable grease frames .enable_webtransport(true) // Enable WebTransport .enable_extended_connect(true) // Enable extended CONNECT .enable_datagram(true) // Enable HTTP/3 datagrams .max_webtransport_sessions(10) // Max concurrent WebTransport sessions .build(quic_conn) .await?; Ok(connection) } ``` -------------------------------- ### Configure HTTP/3 Client Settings Source: https://context7.com/hyperium/h3/llms.txt Builds an HTTP/3 client with custom settings before establishing the connection. Allows configuration of header size, grease frames, datagrams, and extended CONNECT protocol. ```rust use h3::client; use bytes::Bytes; async fn create_client_with_settings(quic_conn: C) -> Result<(), h3::error::ConnectionError> where C: h3::quic::Connection, { let (connection, send_request) = client::builder() .max_field_section_size(8192) // Max header size in bytes .send_grease(true) // Enable grease for forward compatibility .enable_datagram(true) // Enable HTTP/3 datagrams .enable_extended_connect(true) // Enable extended CONNECT protocol .build(quic_conn) .await?; Ok(()) } ``` -------------------------------- ### Launch Chromium with QUIC Enabled Source: https://github.com/hyperium/h3/blob/master/examples/readme.md Launch the Chromium browser with QUIC enabled and force it to use the h3 protocol for a specific origin. This allows testing h3 functionality directly from the browser. ```bash > chromium --enable-quic --quic-version=h3 --origin-to-force-quic-on=localhost:4433 ``` -------------------------------- ### Tag Release Source: https://github.com/hyperium/h3/blob/master/docs/PUBLISH.md Create a Git tag for the release. Replace 'h3' and 'X.Y.Z' with the crate name and version. ```bash git tag h3-vX.Y.Z ``` -------------------------------- ### Publish Crate Source: https://github.com/hyperium/h3/blob/master/docs/PUBLISH.md Use this command to publish a specific crate. Replace 'h3' with the actual crate name. ```bash cargo publish -p h3 ``` -------------------------------- ### Client API - Connection Handshake Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Establishes a new HTTP/3 client connection using default or custom configurations. ```APIDOC ## Client API - Connection Handshake ### Description Initiates the HTTP/3 connection handshake for the client. ### Method `client::handshake` and `Connection::builder().handshake()` ### Endpoint N/A (Function call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust // Using default configuration let client_connection = client::handshake(quic_connection).await?; // Using a builder for custom configuration let client_connection = Connection::builder() .max_field_section_size(1024 * 64) .handshake(quic_connection) .await?; ``` ### Response #### Success Response (200) `client::Connection` - An established HTTP/3 client connection. #### Response Example (Conceptual - actual return is a struct) ```rust // client::Connection ``` ``` -------------------------------- ### Server API - Connection Handshake Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Establishes a new HTTP/3 server connection using default or custom configurations. ```APIDOC ## Server API - Connection Handshake ### Description Initiates the HTTP/3 connection handshake for the server. ### Method `server::handshake` and `Connection::builder().handshake()` ### Endpoint N/A (Function call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust // Using default configuration let server_connection = server::handshake(quic_connection).await?; // Using a builder for custom configuration let server_connection = Connection::builder() .max_field_section_size(1024 * 32) .handshake(quic_connection) .await?; ``` ### Response #### Success Response (200) `server::Connection` - An established HTTP/3 server connection. #### Response Example (Conceptual - actual return is a struct) ```rust // server::Connection ``` ``` -------------------------------- ### Server: Send Response Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Sends the initial HTTP response, including status code and headers. This is the first step in constructing a response to an incoming request. ```rust impl, B: Buf> RequestStream { /// Send a response for the request. pub async fn send_response(&mut self: Response<()>) -> Result<(), Error>; } ``` -------------------------------- ### Handle Incoming HTTP/3 Requests Source: https://context7.com/hyperium/h3/llms.txt Accept and process incoming HTTP/3 requests with proper request/response lifecycle handling. This includes resolving requests, reading bodies, and sending responses. ```rust use h3::server::{Connection, RequestResolver, RequestStream}; use h3::quic; use bytes::{Bytes, BytesMut}; use http::{Request, Response, StatusCode}; use tokio::fs::File; use tokio::io::AsyncReadExt; async fn handle_request( resolver: RequestResolver, ) -> Result<(), Box> where C: quic::Connection, { // Resolve the request (get headers) let (request, mut stream): (Request<()>, RequestStream<_, _>) = resolver.resolve_request().await?; println!("Method: {}", request.method()); println!("URI: {}", request.uri()); println!("Headers: {:?}", request.headers()); // Read request body if present while let Some(mut chunk) = stream.recv_data().await? { use bytes::Buf; println!("Received body chunk: {} bytes", chunk.remaining()); } // Handle based on path let (status, body) = match request.uri().path() { "/" => (StatusCode::OK, Bytes::from("Welcome to HTTP/3!")), "/api/status" => (StatusCode::OK, Bytes::from(r#"{{\"status\": \"ok\"}}"#)), _ => (StatusCode::NOT_FOUND, Bytes::from("Not Found")), }; // Send response let response = Response::builder() .status(status) .header("content-type", "text/plain") .body(())?; stream.send_response(response).await?; stream.send_data(body).await?; stream.finish().await?; Ok(()) } ``` ```rust // File server example async fn serve_file( request: Request<()>, mut stream: RequestStream, root_dir: &str, ) -> Result<(), Box> where C: quic::BidiStream, { let path = format!("{}{}", root_dir, request.uri().path()); match File::open(&path).await { Ok(mut file) => { // Send 200 OK let response = Response::builder() .status(StatusCode::OK) .body(())?; stream.send_response(response).await?; // Stream file contents loop { let mut buf = BytesMut::with_capacity(8192); if file.read_buf(&mut buf).await? == 0 { break; } stream.send_data(buf.freeze()).await?; } } Err(_) => { let response = Response::builder() .status(StatusCode::NOT_FOUND) .body(())?; stream.send_response(response).await?; } } stream.finish().await?; Ok(()) } ``` -------------------------------- ### Server API - Accepting Requests Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Handles the process of accepting incoming HTTP requests on a server connection. ```APIDOC ## Server API - Accepting Requests ### Description Accepts an incoming HTTP request and provides a stream for handling request and response. ### Method `Connection::accept` ### Endpoint N/A (Method on `Connection` struct) ### Parameters None ### Request Example ```rust let (request, request_stream) = server_connection.accept().await?; ``` ### Response #### Success Response (200) - **Request** (`http::Request<()>`): The incoming HTTP request. - **RequestStream** (`server::RequestStream`): A stream for interacting with the request and sending a response. #### Response Example ```rust // (request, request_stream) ``` ``` -------------------------------- ### Demonstrate HTTP/3 Error Codes Source: https://context7.com/hyperium/h3/llms.txt Illustrates the usage of standard HTTP/3 error codes, including codes for graceful closure, protocol violations, internal errors, and request-related issues. ```rust use h3::error::{ConnectionError, StreamError, Code}; // Using error codes fn demonstrate_error_codes() { // Standard HTTP/3 error codes let no_error = Code::H3_NO_ERROR; // 0x100 - Graceful close let general = Code::H3_GENERAL_PROTOCOL_ERROR; // Protocol violation let internal = Code::H3_INTERNAL_ERROR; // Internal error let stream_creation = Code::H3_STREAM_CREATION_ERROR; let closed_critical = Code::H3_CLOSED_CRITICAL_STREAM; let frame_unexpecte d= Code::H3_FRAME_UNEXPECTED; let frame_error = Code::H3_FRAME_ERROR; let excessive_load = Code::H3_EXCESSIVE_LOAD; let id_error = Code::H3_ID_ERROR; let settings_error = Code::H3_SETTINGS_ERROR; let missing_settings = Code::H3_MISSING_SETTINGS; let request_rejected = Code::H3_REQUEST_REJECTED; let request_cancelled = Code::H3_REQUEST_CANCELLED; let request_incomplete = Code::H3_REQUEST_INCOMPLETE; let message_error = Code::H3_MESSAGE_ERROR; let connect_error = Code::H3_CONNECT_ERROR; let version_fallback = Code::H3_VERSION_FALLBACK; } ``` -------------------------------- ### Configure WebTransport Server Source: https://context7.com/hyperium/h3/llms.txt Set up an h3 server with WebTransport support enabled. This configuration allows for a maximum of 10 WebTransport sessions and enables extended CONNECT and datagram protocols. ```rust use h3::server; use h3::ext::Protocol; use h3_webtransport::server::WebTransportSession; use bytes::Bytes; use http::Method; async fn webtransport_server( quic_conn: C, ) -> Result<(), Box> where C: h3::quic::Connection + Clone, { // Configure server with WebTransport support let mut h3_conn = server::builder() .enable_webtransport(true) .enable_extended_connect(true) .enable_datagram(true) .max_webtransport_sessions(10) .build(quic_conn) .await?; while let Ok(Some(resolver)) = h3_conn.accept().await { let (request, stream) = resolver.resolve_request().await?; // Check for WebTransport CONNECT request if request.method() == Method::CONNECT && request.extensions().get::() == Some(&Protocol::WEB_TRANSPORT) { // Accept WebTransport session let session: WebTransportSession<_, Bytes> = WebTransportSession::accept(request, stream, h3_conn).await?; let session_id = session.session_id(); println!("WebTransport session established: {:?}", session_id); // Handle bidirectional streams tokio::spawn(async move { while let Ok(Some(stream)) = session.accept_bi().await { // Handle bidirectional stream... } }); return Ok(()) } } Ok(()) } ``` -------------------------------- ### Send POST Request with Body and Trailers Source: https://context7.com/hyperium/h3/llms.txt Use this to send POST requests that include a request body and optional trailing headers. Ensure the `h3::client::SendRequest` is properly initialized. ```rust use h3::client::SendRequest; use http::{Request, HeaderMap}; use bytes::Bytes; async fn send_post_request( mut send_request: SendRequest, ) -> Result<(), h3::error::StreamError> where T: h3::quic::OpenStreams, { // Build POST request let request = Request::post("https://example.com/upload") .header("content-type", "application/json") .body(())?; // Send request headers let mut stream = send_request.send_request(request).await?; // Send body data in chunks stream.send_data(Bytes::from(r#"{"name": "test"}"#)).await?; stream.send_data(Bytes::from(r#"{"more": "data"}"#)).await?; // Send trailers (optional) - this also finishes the stream let mut trailers = HeaderMap::new(); trailers.insert("x-checksum", "abc123".parse()?); stream.send_trailers(trailers).await?; // Receive response let response = stream.recv_response().await?; println!("Upload status: {}", response.status()); Ok(()) } ``` -------------------------------- ### Push Tag Source: https://github.com/hyperium/h3/blob/master/docs/PUBLISH.md Push the newly created Git tag to the remote repository. Replace 'h3' and 'X.Y.Z' accordingly. ```bash git push upstream h3-v.X.Y.Z ``` -------------------------------- ### Client: Send HTTP/3 Request Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Sends an HTTP/3 request using the client connection. This method initiates a request and returns a `RequestStream` for managing the request and its response. ```rust impl, B: Buf> Connection { pub fn send_request(&mut self, req: http::Request<()>) -> Result, Error>; } ``` -------------------------------- ### Server: Accept HTTP/3 Request Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Accepts an incoming HTTP/3 request and its associated stream. This method is part of the server connection and provides access to the request details and a stream for sending the response. ```rust impl, B: Buf> Connection { pub async fn accept(&mut self) -> Result<(Request<()>, RequestStream), Error>; } ``` -------------------------------- ### Handle Extended CONNECT Requests Source: https://context7.com/hyperium/h3/llms.txt Process incoming HTTP/3 connections to detect and handle extended CONNECT requests, specifically identifying protocols like WebTransport, CONNECT-UDP, CONNECT-IP, and WebSocket. ```rust use h3::ext::Protocol; use h3::server::{Connection, RequestResolver}; use http::{Method, Request}; use bytes::Bytes; async fn handle_extended_connect( mut connection: Connection, ) -> Result<(), Box> where C: h3::quic::Connection, { while let Ok(Some(resolver)) = connection.accept().await { let (request, stream) = resolver.resolve_request().await?; // Check for extended CONNECT if request.method() == Method::CONNECT { // Get the :protocol pseudo-header from extensions if let Some(protocol) = request.extensions().get::() { match *protocol { Protocol::WEB_TRANSPORT => { println!("WebTransport session requested"); // Handle WebTransport... } Protocol::CONNECT_UDP => { println!("CONNECT-UDP (RFC 9298) requested"); // Handle UDP proxying... } Protocol::CONNECT_IP => { println!("CONNECT-IP (RFC 9484) requested"); // Handle IP proxying... } Protocol::WEBSOCKET => { println!("WebSocket over HTTP/3 requested"); // Handle WebSocket... } _ => { println!("Unknown protocol: {}", protocol.as_str()); } } } } } Ok(()) } ``` -------------------------------- ### Client: Poll Connection Readiness Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Polls to determine if the client connection is ready to send a new request. This is essential for managing the flow of outgoing requests. ```rust impl, B: Buf> Connection { /// Polls for when the client can send a new request. pub fn poll_ready(&mut self, cx: &mut Context) -> Poll>; } ``` -------------------------------- ### Graceful Server Shutdown Source: https://context7.com/hyperium/h3/llms.txt Initiate graceful shutdown allowing in-flight requests to complete. The connection will automatically close when all streams complete or when the Connection is dropped. ```rust use h3::server::Connection; use bytes::Buf; async fn shutdown_server( mut connection: Connection, ) -> Result<(), h3::error::ConnectionError> where C: h3::quic::Connection, B: Buf, { // Initiate shutdown, allowing up to 5 more requests connection.shutdown(5).await?; // Connection will automatically close when all streams complete // or when the Connection is dropped Ok(()) } ``` -------------------------------- ### Server: Send Response Trailers Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Sends optional trailers to conclude the response. This is used to send final metadata after the response body has been sent. ```rust impl, B: Buf> RequestStream { /// Send a set of trailers to end the response. pub async fn send_trailers(&mut self, trailers: HeaderMap) -> Result<(), Error>; } ``` -------------------------------- ### Client API - Sending Requests Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Handles the process of sending outgoing HTTP requests on a client connection. ```APIDOC ## Client API - Sending Requests ### Description Sends an HTTP request and returns a stream for handling the response. ### Method `Connection::send_request` ### Endpoint N/A (Method on `Connection` struct) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - `req` (`http::Request<()>`): The HTTP request to send. ### Request Example ```rust let request = http::Request::builder().uri("/").body(()).unwrap(); let request_stream = client_connection.send_request(request).await?; ``` ### Response #### Success Response (200) - `RequestStream` (`client::RequestStream`): A stream for interacting with the response. #### Response Example ```rust // request_stream ``` ``` -------------------------------- ### Implement h3 Connection Trait for Custom QUIC Source: https://context7.com/hyperium/h3/llms.txt Implement the `Connection` trait for your custom QUIC transport. This involves handling incoming streams and providing a stream opener. Ensure your implementation correctly polls for new streams and connection errors. ```rust use h3::quic::{ Connection, OpenStreams, SendStream, RecvStream, BidiStream, StreamId, WriteBuf, ConnectionErrorIncoming, StreamErrorIncoming, }; use bytes::Buf; use std::task::{Context, Poll}; // Main connection trait impl Connection for MyQuicConnection { type RecvStream = MyRecvStream; type OpenStreams = MyOpenStreams; fn poll_accept_recv( &mut self, cx: &mut Context<'_>, ) -> Poll> { // Accept incoming unidirectional stream todo!() } fn poll_accept_bidi( &mut self, cx: &mut Context<'_>, ) -> Poll> { // Accept incoming bidirectional stream todo!() } fn opener(&self) -> Self::OpenStreams { // Return stream opener todo!() } } ``` -------------------------------- ### Server: Receive Request Trailers Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Receives optional trailers sent by the client after the request body. This allows for metadata transmission at the end of a request. ```rust impl RequestStream { /// Receive an optional set of trailers for the request. pub async fn recv_trailers(&mut self) -> Result, Error>; } ``` -------------------------------- ### Server: Split RequestStream Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Splits a bidirectional `RequestStream` into two separate streams: one for sending and one for receiving. This allows for concurrent handling of send and receive operations. ```rust impl, B> RequestStream { /// Split this "bidi" `RequestStream` into two sides, one with /// a `SendStream` and the other with a `RecvStream`. pub fn split(self) -> (RequestStream, B>, RequestStream); } ``` -------------------------------- ### Handle HTTP/3 Connection Errors Source: https://context7.com/hyperium/h3/llms.txt Use this function to match and handle different types of HTTP/3 connection errors, including local, remote, and timeout errors. It also checks for graceful connection closures. ```rust use h3::error::{ConnectionError, StreamError, Code}; fn handle_connection_error(error: ConnectionError) { match error { ConnectionError::Local { error } => { println!("Local error: {:?}", error); } ConnectionError::Remote(remote_err) => { println!("Remote closed connection: {:?}", remote_err); } ConnectionError::Timeout => { println!("Connection timed out"); } } // Check for graceful close if error.is_h3_no_error() { println!("Connection closed gracefully"); } } ``` -------------------------------- ### Send HTTP Request and Receive Response Source: https://context7.com/hyperium/h3/llms.txt Sends an HTTP request using the `SendRequest` handle and processes the response. Handles receiving headers, body chunks, and optional trailers. The `SendRequest` sender can be cloned for concurrent requests. ```rust use h3::client::SendRequest; use http::{Request, Response}; use bytes::Bytes; async fn send_get_request( mut send_request: SendRequest, ) -> Result, h3::error::StreamError> where T: h3::quic::OpenStreams, { // Build HTTP request let request = Request::get("https://example.com/api/data") .header("accept", "application/json") .body(())?; // Send request - returns a bidirectional stream let mut stream = send_request.send_request(request).await?; // Finish sending (no body) stream.finish().await?; // Receive response headers let response = stream.recv_response().await?; println!("Status: {}", response.status()); println!("Headers: {:?}", response.headers()); // Receive response body chunks while let Some(mut chunk) = stream.recv_data().await? { use bytes::Buf; let data = chunk.copy_to_bytes(chunk.remaining()); println!("Received {} bytes", data.len()); } // Optionally receive trailers if let Some(trailers) = stream.recv_trailers().await? { println!("Trailers: {:?}", trailers); } Ok(response) } ``` -------------------------------- ### Connection Trait Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md The `Connection` trait defines the interface for managing QUIC connections, including the creation and acceptance of unidirectional and bidirectional streams. ```APIDOC ## trait Connection ### Description Defines the interface for managing QUIC connections, including the creation and acceptance of unidirectional and bidirectional streams. ### Type Parameters - `B`: A type that implements the `Buf` trait, representing the buffer for stream data. ### Associated Types - `SendStream`: The type representing a unidirectional send stream. - `RecvStream`: The type representing a unidirectional receive stream. - `BidiStream`: The type representing a bidirectional stream (both send and receive). - `Error`: The type representing errors that can occur during connection operations. ### Methods #### Accepting Streams - `poll_accept_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll, Self::Error>>`: Polls for the acceptance of an incoming bidirectional stream. - `poll_accept_recv_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll, Self::Error>>`: Polls for the acceptance of an incoming unidirectional receive stream. #### Creating Streams - `poll_open_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll>`: Polls for the opening of a new bidirectional stream. - `poll_open_send_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll>`: Polls for the opening of a new unidirectional send stream. ### Example ```rust trait Connection { type SendStream: SendStream; type RecvStream: RecvStream; type BidiStream: SendStream + RecvStream; type Error; // Accepting streams fn poll_accept_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll, Self::Error>>; fn poll_accept_recv_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll, Self::Error>>; // Creating streams fn poll_open_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll>; fn poll_open_send_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll>; } ``` ``` -------------------------------- ### Handle HTTP/3 Stream Errors Source: https://context7.com/hyperium/h3/llms.txt This function demonstrates how to handle various HTTP/3 stream errors, such as protocol violations, remote terminations, and header size issues. It also includes a check for streams closed without error. ```rust use h3::error::{ConnectionError, StreamError, Code}; fn handle_stream_error(error: StreamError) { match &error { StreamError::StreamError { code, reason } => { println!("Stream error {}: {}", code, reason); } StreamError::RemoteTerminate { code } => { println!("Remote terminated stream with code: {}", code); } StreamError::ConnectionError(conn_err) => { println!("Underlying connection error: {}", conn_err); } StreamError::HeaderTooBig { actual_size, max_size } => { println!("Header too large: {} > {}", actual_size, max_size); } StreamError::RemoteClosing => { println!("Remote is closing, cannot perform stream operations"); } StreamError::Undefined(err) => { println!("Undefined error: {}", err); } } // Check for no-error close if error.is_h3_no_error() { println!("Stream closed without error"); } } ``` -------------------------------- ### Graceful Connection Shutdown Source: https://context7.com/hyperium/h3/llms.txt Implement graceful shutdown for an h3 client connection. This function waits for ongoing requests to complete before closing the connection, or initiates shutdown upon receiving a signal. ```rust use h3::client::Connection; use bytes::Buf; use futures::future; use tokio::sync::oneshot; async fn graceful_shutdown( mut connection: Connection, shutdown_rx: oneshot::Receiver, ) -> Result<(), h3::error::ConnectionError> where C: h3::quic::Connection + Send + 'static, C::SendStream: Send, C::RecvStream: Send, B: Buf + Send + 'static, { tokio::select! { // Drive connection normally closed = future::poll_fn(|cx| connection.poll_close(cx)) => { if closed.is_h3_no_error() { println!("Connection closed normally"); } Ok(()) } // Handle shutdown signal max_streams = shutdown_rx => { // Initiate graceful shutdown connection.shutdown(max_streams.unwrap_or(0)).await?; // Wait for completion future::poll_fn(|cx| connection.poll_close(cx)).await; Ok(()) } } } ``` -------------------------------- ### Server API - RequestStream Split Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Allows splitting a bidirectional stream into separate send and receive streams. ```APIDOC ## Server API - RequestStream Split ### Description Splits a bidirectional `RequestStream` into two distinct streams: one for sending and one for receiving. ### Method `RequestStream::split` ### Endpoint N/A (Method on `RequestStream` struct) ### Parameters None ### Request Example ```rust let (send_stream, recv_stream) = request_stream.split(); ``` ### Response #### Success Response (200) - `send_stream` (`RequestStream, B>`): Stream for sending data. - `recv_stream` (`RequestStream`): Stream for receiving data. #### Response Example ```rust // (send_stream, recv_stream) ``` ``` -------------------------------- ### Server API - RequestStream Operations Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Provides methods for receiving request data and sending responses. ```APIDOC ## Server API - RequestStream Operations ### Description Methods to interact with the `RequestStream` for receiving request details and sending HTTP responses. ### Method `recv_data`, `recv_trailers`, `send_response`, `send_data`, `send_trailers` ### Endpoint N/A (Methods on `RequestStream` struct) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - `buf` (`B`): Data buffer for sending response body. - `trailers` (`HeaderMap`): HTTP trailers for request or response. ### Request Example ```rust // Receiving request data let data = request_stream.recv_data().await?; // Receiving request trailers let trailers = request_stream.recv_trailers().await?; // Sending a response request_stream.send_response(response).await?; // Sending response data request_stream.send_data(buf).await?; // Sending response trailers request_stream.send_trailers(trailers).await?; ``` ### Response #### Success Response (200) - `recv_data`: `Option` - Received data chunk or None if stream closed. - `recv_trailers`: `Option` - Received trailers or None. - `send_response`, `send_data`, `send_trailers`: `()` on success. #### Response Example ```rust // For recv_data: // Some(data_buffer) // None // For recv_trailers: // Some(header_map) // None ``` ``` -------------------------------- ### Implement h3 SendStream Trait for Custom QUIC Source: https://context7.com/hyperium/h3/llms.txt Implement the `SendStream` trait for sending data on a unidirectional stream. This includes methods for checking readiness, sending data, finishing the stream, resetting it, and retrieving its ID. ```rust impl SendStream for MySendStream { fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { // Check if stream can accept more data todo!() } fn send_data>>(&mut self, data: T) -> Result<(), StreamErrorIncoming> { // Queue data for sending todo!() } fn poll_finish(&mut self, cx: &mut Context<'_>) -> Poll> { // Finish the send side todo!() } fn reset(&mut self, reset_code: u64) { // Reset the stream todo!() } fn send_id(&self) -> StreamId { // Return stream ID todo!() } } ``` -------------------------------- ### Server: Send Response Body Data Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Sends a chunk of data as part of the response body. This method can be called multiple times to stream the response content. ```rust impl, B: Buf> RequestStream { /// Send some data on the response body. pub async fn send_data(&mut self, buf: B) -> Result<(), Error>; } ``` -------------------------------- ### Implement h3 RecvStream Trait for Custom QUIC Source: https://context7.com/hyperium/h3/llms.txt Implement the `RecvStream` trait for receiving data on a stream. This involves polling for incoming data, stopping the sending process with an error code, and retrieving the stream ID. ```rust impl RecvStream for MyRecvStream { type Buf = bytes::Bytes; fn poll_data( &mut self, cx: &mut Context<'_>, ) -> Poll, StreamErrorIncoming>> { // Poll for incoming data, None means stream finished todo!() } fn stop_sending(&mut self, error_code: u64) { // Send STOP_SENDING frame todo!() } fn recv_id(&self) -> StreamId { // Return stream ID todo!() } } ``` -------------------------------- ### Server: Receive Request Body Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Receives a chunk of the request body. This method is used on the `RequestStream` to read data sent by the client. ```rust impl RequestStream { /// Receive some of the request body. pub async fn recv_data(&mut self) -> Result, Error>; } ``` -------------------------------- ### Implement h3 OpenStreams Trait for Custom QUIC Source: https://context7.com/hyperium/h3/llms.txt Implement the `OpenStreams` trait to manage opening new bidirectional and unidirectional streams. This trait is responsible for initiating new streams and closing the connection with an error code if necessary. ```rust impl OpenStreams for MyOpenStreams { type BidiStream = MyBidiStream; type SendStream = MySendStream; fn poll_open_bidi( &mut self, cx: &mut Context<'_>, ) -> Poll> { // Open new bidirectional stream todo!() } fn poll_open_send( &mut self, cx: &mut Context<'_>, ) -> Poll> { // Open new unidirectional stream todo!() } fn close(&mut self, code: h3::error::Code, reason: &[u8]) { // Close connection with error code todo!() } } ``` -------------------------------- ### QUIC Connection Trait Definition Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Defines the core `Connection` trait for QUIC transport. Users implement this trait to integrate their QUIC connection logic. It specifies associated types for streams and errors, and methods for accepting and opening various stream types. ```rust trait Connection { type SendStream: SendStream; type RecvStream: RecvStream; type BidiStream: SendStream + RecvStream; type Error; // Accepting streams fn poll_accept_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll, Self::Error>>; fn poll_accept_recv_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll, Self::Error>>; // Creating streams fn poll_open_bidirectional_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll>; fn poll_open_send_stream(self: Pin<&mut Self>, cx: &mut Context) -> Poll>; } ``` -------------------------------- ### Define SendStream Trait in Rust Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Defines the `SendStream` trait for sending data over a stream. It includes methods for polling readiness, sending data, and finishing the stream. Consider the bounds for the `Error` type and whether `poll_ready` should take `Pin<&mut Self>`. ```rust trait SendStream { type Error; // bounds? /// Polls that the stream is ready to send more data. // Q: Should this be Pin<&mut Self>? fn poll_ready(&mut self, cx: &mut Context) -> Poll>; fn send_data(&mut self, data: B) -> Result<(), Self::Error>; // fn poll_flush? fn poll_finish(&mut self, cx: &mut Context) -> Poll>; fn reset(&mut self, reset_code: u64); } ``` -------------------------------- ### Define BidiStream Trait in Rust Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Defines the `BidiStream` trait, which combines `SendStream` and `RecvStream` for bidirectional communication. It includes a `split` method to separate the stream into its send and receive halves. ```rust trait BidiStream: SendStream + RecvStream { type SendStream: SendStream; type RecvStream: RecvStream; fn split(self) -> (Self::SendStream, Self::RecvStream); } ``` -------------------------------- ### Define RecvStream Trait in Rust Source: https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md Defines the `RecvStream` trait for receiving data from a stream. It provides methods to poll for incoming data and to stop sending data with an error code. The `Buf` and `Error` types are generic parameters. ```rust trait RecvStream { type Buf: Buf; type Error; // bounds? // Poll for more data received from the remote on this stream. fn poll_data(&mut self, cx: &mut Context) -> Poll, Self::Error>>; fn stop_sending(&mut self, error_code: u64); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.