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;
69mod upgrade;
70
71pub use early_hints::*;
72#[cfg(feature = "h1")]
73pub use h1::*;
74#[cfg(feature = "h2")]
75pub use h2::*;
76#[cfg(feature = "h3")]
77pub use h3::*;
78pub use incoming::*;
79pub use upgrade::*;
80
81use http::{Request, Response};
82use http_body::Body;
83
84/// A trait representing an HTTP protocol (for example, HTTP/1.1, HTTP/2, HTTP/3).
85///
86/// This trait provides a simple, type-erased interface for handling HTTP requests
87/// across different protocol versions.
88pub trait HttpProtocol: Sized {
89 fn handle<F, Fut, ResB, ResBE, ResE>(
90 self,
91 request_fn: F,
92 ) -> impl std::future::Future<Output = Result<(), std::io::Error>>
93 where
94 F: Fn(Request<Incoming>) -> Fut + 'static,
95 Fut: std::future::Future<Output = Result<Response<ResB>, ResE>> + 'static,
96 ResB: Body<Data = bytes::Bytes, Error = ResBE> + Unpin + 'static,
97 ResE: std::error::Error,
98 ResBE: std::error::Error;
99
100 #[allow(unused_variables)]
101 #[inline]
102 fn handle_with_error_fn<F, Fut, ResB, ResBE, ResE, EF, EFut, EResB, EResBE, EResE>(
103 self,
104 request_fn: F,
105 error_fn: EF,
106 ) -> impl std::future::Future<Output = Result<(), std::io::Error>>
107 where
108 F: Fn(Request<Incoming>) -> Fut + 'static,
109 Fut: std::future::Future<Output = Result<Response<ResB>, ResE>> + 'static,
110 ResB: Body<Data = bytes::Bytes, Error = ResBE> + Unpin + 'static,
111 ResE: std::error::Error,
112 ResBE: std::error::Error,
113 EF: FnOnce(bool) -> EFut,
114 EFut: std::future::Future<Output = Result<Response<EResB>, EResE>>,
115 EResB: Body<Data = bytes::Bytes, Error = EResBE> + Unpin + 'static,
116 EResE: std::error::Error,
117 EResBE: std::error::Error,
118 {
119 self.handle(request_fn)
120 }
121}