hyperdriver/server/
mod.rs

1//! A server framework with connection management, automatic HTTP/1.1 and HTTP/2
2//! switching, and pluggable acceptors, protocols, and services.
3//!
4//! # Overview
5//! [`Server`] is the primary entry point for this module, and represents the components
6//! which are ready to serve requests. It has a builder API for confiugration, [`Server::builder`]
7//! and can be `await`-ed to start serving connections.
8//!
9//! When a new connection arrives, it is the acceptor's job to accept the connection and
10//! provide a bi-directional stream of bytes. The server then uses the protocol to determine
11//! how to handle that connection and serve requests. A service is used to handle individual
12//! requests. The service is generated by the "MakeService" which is provided by the user.
13//!
14//! A "MakeService" is a service which creates services, aka a service factory. The service
15//! factory will recieve a reference to the underlying connection stream.
16//!
17//! # Low Level Components
18//! The [`conn`] module contains the low-level components that are used to build a server,
19//! including the built in acceptors and protocols. These can be used to build custom servers
20//! with different behavior, or to extend the built-in server with custom acceptors or protocols.
21//!
22//! # Example
23//! ```rust
24//! # use hyperdriver::Body;
25//! # use hyperdriver::server::{ServerAcceptorExt, ServerProtocolExt};
26//! # type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
27//!
28//! async fn echo(req: http::Request<Body>) -> Result<http::Response<Body>, BoxError> {
29//!     Ok(http::Response::new(req.into_body()))
30//! }
31//!
32//! async fn example_server() {
33//!     let (client, incoming) = hyperdriver::stream::duplex::pair();
34//!
35//!    let server = hyperdriver::server::Server::builder()
36//!     .with_incoming(incoming)
37//!     .with_http1()
38//!     .with_shared_service(tower::service_fn(echo))
39//!     .with_tokio();
40//!
41//!     server.await.unwrap();
42//! }
43
44mod builder;
45pub mod conn;
46
47pub use self::builder::{ServerAcceptorExt, ServerConnectionInfoExt, ServerProtocolExt};
48pub use self::conn::auto::Builder as AutoBuilder;
49pub use chateau::server::{Accept, Connection, Protocol};
50pub use chateau::server::{GracefulShutdown, Server, ServerError, Serving};
51
52#[cfg(test)]
53mod tests {
54
55    use std::{
56        convert::Infallible,
57        future::{IntoFuture, ready},
58    };
59
60    use super::{builder::ServerProtocolExt as _, *};
61    use crate::Body;
62    use chateau::stream::duplex;
63
64    use chateau::services::make_service_fn;
65    use tower::service_fn;
66
67    #[allow(dead_code, unused_must_use)]
68    fn compile() {
69        let svc = make_service_fn(|_| {
70            ready(Ok::<_, Infallible>(service_fn(|_: http::Request<Body>| {
71                ready(Ok::<_, Infallible>(http::Response::new(crate::Body::from(
72                    "hello",
73                ))))
74            })))
75        });
76
77        let (_, incoming) = duplex::pair();
78
79        let server = Server::builder::<http::Request<Body>>()
80            .with_acceptor(incoming)
81            .with_make_service(svc)
82            .with_auto_http()
83            .with_request::<http::Request<crate::Body>>()
84            .with_tokio();
85
86        server.into_future();
87    }
88}