Skip to main content

vibeio_http/
lib.rs

1//! # vibeio-http
2//!
3//! High-performance HTTP/1.1, HTTP/2, and experimental HTTP/3 server implementation
4//! for the [`vibeio`] async runtime.
5//!
6//! `vibeio-http` provides protocol-specific connection handlers behind a common
7//! [`HttpProtocol`] trait. Handlers receive an `http::Request<`[`Incoming`]`>`
8//! and return an `http::Response<B>` where `B` implements
9//! [`http_body::Body`] with `bytes::Bytes` chunks.
10//!
11//! ## Feature highlights
12//!
13//! - **Zero-copy static file serving** - supports zero-copy response sending for static file serving on Linux.
14//! - **100 Continue** - Supports automatically sending `100 Continue` before the final response.
15//! - **103 Early Hints** - Supports sending `103 Early Hints` before the final response.
16//!
17//! ## Feature flags
18//!
19//! - `h1`: Enables HTTP/1.x support.
20//! - `h2`: Enables HTTP/2 support.
21//! - `h3`: Enables HTTP/3 support.
22//! - `h1-zerocopy`: Enables Linux-only zero-copy response sending for HTTP/1.x.
23//!
24//! ## Early hints
25//!
26//! Use [`send_early_hints`] from a request handler to send `103 Early Hints`
27//! before the final response.
28//!
29//! ## Example
30//!
31//! ```rust,no_run
32//! # #[cfg(feature = "h1")]
33//! # fn main() -> std::io::Result<()> {
34//! use bytes::Bytes;
35//! use http::Response;
36//! use http_body_util::Full;
37//! use vibeio::net::TcpListener;
38//! use vibeio::RuntimeBuilder;
39//! use vibeio_http::{Http1, Http1Options, HttpProtocol};
40//!
41//! let runtime = RuntimeBuilder::new().enable_timer(true).build()?;
42//!
43//! runtime.block_on(async {
44//!     let listener = TcpListener::bind("127.0.0.1:8080")?;
45//!     let (stream, _) = listener.accept().await?;
46//!     stream.set_nodelay(true)?;
47//!
48//!     Http1::new(stream.into_poll()?, Http1Options::default())
49//!         .handle(|_request| async move {
50//!             let response = Response::new(Full::new(Bytes::from_static(b"Hello World")));
51//!             Ok::<_, std::convert::Infallible>(response)
52//!         })
53//!         .await
54//! })
55//! # }
56//! # #[cfg(not(feature = "h1"))]
57//! # fn main() {}
58//! ```
59#![cfg_attr(docsrs, feature(doc_cfg))]
60
61mod early_hints;
62#[cfg(feature = "h1")]
63mod h1;
64#[cfg(feature = "h2")]
65mod h2;
66#[cfg(feature = "h3")]
67mod h3;
68mod incoming;
69
70pub use early_hints::*;
71#[cfg(feature = "h1")]
72pub use h1::*;
73#[cfg(feature = "h2")]
74pub use h2::*;
75#[cfg(feature = "h3")]
76pub use h3::*;
77pub use incoming::*;
78
79use http::{Request, Response};
80use http_body::Body;
81
82/// A trait representing an HTTP protocol (for example, HTTP/1.1, HTTP/2, HTTP/3).
83///
84/// This trait provides a simple, type-erased interface for handling HTTP requests
85/// across different protocol versions.
86pub trait HttpProtocol: Sized {
87    fn handle<F, Fut, ResB, ResBE, ResE>(
88        self,
89        request_fn: F,
90    ) -> impl std::future::Future<Output = Result<(), std::io::Error>>
91    where
92        F: Fn(Request<Incoming>) -> Fut + 'static,
93        Fut: std::future::Future<Output = Result<Response<ResB>, ResE>>,
94        ResB: Body<Data = bytes::Bytes, Error = ResBE> + Unpin,
95        ResE: std::error::Error,
96        ResBE: std::error::Error;
97
98    #[allow(unused_variables)]
99    #[inline]
100    fn handle_with_error_fn<F, Fut, ResB, ResBE, ResE, EF, EFut, EResB, EResBE, EResE>(
101        self,
102        request_fn: F,
103        error_fn: EF,
104    ) -> impl std::future::Future<Output = Result<(), std::io::Error>>
105    where
106        F: Fn(Request<Incoming>) -> Fut + 'static,
107        Fut: std::future::Future<Output = Result<Response<ResB>, ResE>>,
108        ResB: Body<Data = bytes::Bytes, Error = ResBE> + Unpin,
109        ResE: std::error::Error,
110        ResBE: std::error::Error,
111        EF: FnOnce(bool) -> EFut,
112        EFut: std::future::Future<Output = Result<Response<EResB>, EResE>>,
113        EResB: Body<Data = bytes::Bytes, Error = EResBE> + Unpin,
114        EResE: std::error::Error,
115        EResBE: std::error::Error,
116    {
117        self.handle(request_fn)
118    }
119}