diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..f132139 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: joseluisq +custom: paypal.me/joseluisqs diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..3ae0dd2 --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,28 @@ +name: audit +on: + schedule: + - cron: '20 01 * * *' # Every day at 01:20 UTC + push: + branches: + - master + paths: + - "**/Cargo.lock" + - "**/Cargo.toml" + pull_request: + branches: + - master + paths: + - "**/Cargo.lock" + - "**/Cargo.toml" + +jobs: + audit: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/devel.yml b/.github/workflows/devel.yml new file mode 100644 index 0000000..e59a426 --- /dev/null +++ b/.github/workflows/devel.yml @@ -0,0 +1,151 @@ +name: devel +on: + pull_request: + paths: + - .github/workflows/devel.yml + - .cargo/config.toml + - Cargo.lock + - Cargo.toml + - src/** + push: + branches: + - master + - staging + - trying + paths: + - .github/workflows/devel.yml + - Cargo.lock + - Cargo.toml + - src/** + schedule: + - cron: '15 01 * * *' # Every day at 01:15 UTC + +jobs: + test: + name: test + runs-on: ${{ matrix.os }} + env: + # Cargo binary + CARGO_BIN: cargo + # When CARGO_BIN is set to CROSS, this is set to `--target matrix.target` + TARGET_FLAGS: "" + # When CARGO_BIN is set to CROSS, TARGET_DIR includes matrix.target + TARGET_DIR: ./target + # Emit backtraces on panics + RUST_BACKTRACE: 1 + # Skip tests + SKIP_TESTS: "" + strategy: + matrix: + build: + - pinned + - linux-musl + - linux-gnu + - macos + - windows-msvc + include: + # Specific Rust channels. + # We test against the latest and minimum Rust stable version. + - build: pinned + os: ubuntu-22.04 + rust: 1.70.0 + # Some of our release builds are generated by a nightly compiler to take + # advantage of the latest optimizations/compile time improvements. + - build: linux-musl + os: ubuntu-22.04 + rust: stable + target: x86_64-unknown-linux-musl + - build: linux-gnu + os: ubuntu-22.04 + rust: stable + target: x86_64-unknown-linux-gnu + - build: macos + os: macos-12 + rust: stable + target: x86_64-apple-darwin + - build: windows-msvc + os: windows-2022 + rust: stable + target: x86_64-pc-windows-msvc + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ matrix.rust }} + target: ${{ matrix.target }} + + - name: Set up Cross + if: ${{ !contains(matrix.os, 'windows') && matrix.target != '' }} + shell: bash + run: | + target='' + case "${{ matrix.os }}" in + *macos*) + target=x86_64-apple-darwin + ;; + *) + target=x86_64-unknown-linux-musl + ;; + esac + + echo "Installing cross..." + curl -sSL \ + "https://github.com/cross-rs/cross/releases/download/v0.2.5/cross-$target.tar.gz" \ + | sudo tar zxf - -C /usr/local/bin/ cross cross-util + cross -V + echo "CARGO_BIN=/usr/local/bin/cross" >> $GITHUB_ENV + + - name: Setup Cargo + shell: bash + run: | + if [[ "${{ matrix.target }}" != "" ]]; then + echo "TARGET_FLAGS=--target=${{ matrix.target }}" >> $GITHUB_ENV + echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV + fi + echo "cargo command is: ${{ env.CARGO_BIN }}" + echo "target flag is: ${{ env.TARGET_FLAGS }}" + echo "target dir is: ${{ env.TARGET_DIR }}" + + - name: Run tests + shell: bash + run: | + ${{ env.CARGO_BIN }} test --verbose ${{ env.TARGET_FLAGS }} ${{ env.SKIP_TESTS }} + + - name: Run build + shell: bash + run: | + ${{ env.CARGO_BIN }} build --example server --verbose ${{ env.TARGET_FLAGS }} + + checks: + name: checks + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Install stable toolchain + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + components: rustfmt, clippy + + - name: Check formatting + run: | + cargo fmt --all -- --check + + - name: Check via Clippy + run: | + cargo clippy --all-features -- -D warnings + + - name: Check crate docs + run: | + cargo doc --lib --no-deps diff --git a/Cargo.toml b/Cargo.toml index cd77433..5cf6cac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ authors = ["Jose Quintana "] license = "MIT OR Apache-2.0" repository = "https://github.com/static-web-server/hyper-middleware" documentation = "https://docs.rs/hyper-middleware" -edition = "2018" +edition = "2021" +rust-version = "1.56.0" categories = ["network-programming", "web-programming::http-server"] include = [ "src/**/*.rs", @@ -25,12 +26,22 @@ keywords = [ ] [dependencies] -hyper = { version = "0.14.27", default-features = false, features = ["server", "tcp"] } -anyhow = "1.0.75" -thiserror = "1.0.50" -async-trait = "0.1.74" +hyper = { version = "0.14.28", default-features = false, features = ["server", "tcp"] } +anyhow = "1.0.79" +thiserror = "1.0.56" +async-trait = "0.1.77" async-recursion = "1.0.5" [dev-dependencies] hyper = { version = "0.14", features = ["tcp", "server", "http1"] } tokio = { version = "1", features = ["rt-multi-thread", "macros"], default-features = false } + +[profile.release] +codegen-units = 1 +debug = false +debug-assertions = false +lto = "fat" +opt-level = 3 +panic = "abort" +rpath = false +strip = true diff --git a/README.md b/README.md index c81ddd1..2f0383c 100644 --- a/README.md +++ b/README.md @@ -12,20 +12,20 @@ - Compact Middleware and Handler System inspired by [The Iron Framework](https://github.com/iron/iron). - Simple [Hyper Service](https://docs.rs/hyper/latest/hyper/service/trait.Service.html) with convenient __Remote Address__ access. - Convenient `Error` and `Result` types powered by [anyhow](https://github.com/dtolnay/anyhow). +- `Async` support via [async-trait](https://github.com/dtolnay/async-trait). +- Macros to facilitate HTTP response errors or error casting. ## Example [examples/server.rs](examples/server.rs) ```rust -#![deny(warnings)] - use hyper::{header, Server, StatusCode}; -use std::{net::SocketAddr, path::PathBuf}; use hyper_middleware::{ - async_trait, AfterMiddleware, BeforeMiddleware, Body, Chain, Error, Handler, Request, Response, - Result, Service, + async_trait, AfterMiddleware, BeforeMiddleware, Body, Error, Handler, Middlewares, Request, + Response, Result, Service, }; +use std::{net::SocketAddr, path::PathBuf}; struct Config { pub root: PathBuf, @@ -39,17 +39,18 @@ struct Application { impl Handler for Application { async fn handle(&self, req: &mut Request) -> Result { // Access the Hyper incoming Request - println!("Handler - URI Path: {}", req.uri().path()); + println!("Application::handle() - URI Path: {}", req.uri().path()); // Access the custom app options - println!("Config Root: {}", self.opts.root.display()); - - // Access the Remote Address println!( - "Remote Addr: {}", - req.extensions().get::().unwrap() + "Application::handle() - Config Root: {}", + self.opts.root.display() ); + // Access the Remote Address + let remote_addr = req.extensions().get::().unwrap(); + println!("Application::handle() - Remote Addr: {}", remote_addr); + // Create a Hyper Response and send it back to the middlewares chain Ok(Response::new(Body::from("¡Hola!"))) } @@ -60,10 +61,10 @@ struct FirstMiddleware {} #[async_trait] impl BeforeMiddleware for FirstMiddleware { async fn before(&self, req: &mut Request) -> Result { - println!("First Middleware called!"); + println!("FirstMiddleware::before()"); // Access the Hyper incoming Request - println!("First - URI Path: {}", req.uri().path()); + println!("FirstMiddleware::before() - URI Path: {}", req.uri().path()); Ok(()) } @@ -78,7 +79,7 @@ struct SecondMiddleware {} #[async_trait] impl AfterMiddleware for SecondMiddleware { async fn after(&self, _: &mut Request, mut res: Response) -> Result { - println!("Second Middleware called!"); + println!("SecondMiddleware::after()"); // Mutate the Hyper Response at convenience // and send it back to other middlewares on the chain @@ -105,17 +106,15 @@ async fn main() -> Result { root: std::env::current_dir().unwrap(), }; - // 1. Create a custom middleware chain - let mut handler = Chain::new(Application { opts }); + // 1. Create a custom middleware chain and plug in some custom middlewares + let mut middlewares = Middlewares::new(Application { opts }); + middlewares.link_before(FirstMiddleware {}); + middlewares.link_after(SecondMiddleware {}); - // 2. Plug in some custom middlewares - handler.link_before(FirstMiddleware {}); - handler.link_after(SecondMiddleware {}); + // 2. Create a Hyper service and set the current handler with its middlewares + let service = Service::new(middlewares); - // 3. Create a Hyper service and set the current handler with its middlewares - let service = Service::new(handler); - - // 4. Finally just run server using the service already created + // 3. Finally just run server using the service already created let addr = ([127, 0, 0, 1], 8787).into(); let server = Server::bind(&addr).serve(service); @@ -129,7 +128,7 @@ async fn main() -> Result { To run the example just type: -``` +```sh cargo run --example server ``` diff --git a/examples/server.rs b/examples/server.rs index c719413..f6c96be 100644 --- a/examples/server.rs +++ b/examples/server.rs @@ -4,12 +4,11 @@ #![deny(dead_code)] use hyper::{header, Server, StatusCode}; -use std::{net::SocketAddr, path::PathBuf}; - use hyper_middleware::{ - async_trait, AfterMiddleware, BeforeMiddleware, Body, Chain, Error, Handler, Request, Response, - Result, Service, + async_trait, AfterMiddleware, BeforeMiddleware, Body, Error, Handler, Middlewares, Request, + Response, Result, Service, }; +use std::{net::SocketAddr, path::PathBuf}; struct Config { pub root: PathBuf, @@ -23,17 +22,18 @@ struct Application { impl Handler for Application { async fn handle(&self, req: &mut Request) -> Result { // Access the Hyper incoming Request - println!("Handler - URI Path: {}", req.uri().path()); + println!("Application::handle() - URI Path: {}", req.uri().path()); // Access the custom app options - println!("Config Root: {}", self.opts.root.display()); - - // Access the Remote Address println!( - "Remote Addr: {}", - req.extensions().get::().unwrap() + "Application::handle() - Config Root: {}", + self.opts.root.display() ); + // Access the Remote Address + let remote_addr = req.extensions().get::().unwrap(); + println!("Application::handle() - Remote Addr: {}", remote_addr); + // Create a Hyper Response and send it back to the middlewares chain Ok(Response::new(Body::from("¡Hola!"))) } @@ -44,10 +44,10 @@ struct FirstMiddleware {} #[async_trait] impl BeforeMiddleware for FirstMiddleware { async fn before(&self, req: &mut Request) -> Result { - println!("First Middleware called!"); + println!("FirstMiddleware::before()"); // Access the Hyper incoming Request - println!("First - URI Path: {}", req.uri().path()); + println!("FirstMiddleware::before() - URI Path: {}", req.uri().path()); Ok(()) } @@ -62,7 +62,7 @@ struct SecondMiddleware {} #[async_trait] impl AfterMiddleware for SecondMiddleware { async fn after(&self, _: &mut Request, mut res: Response) -> Result { - println!("Second Middleware called!"); + println!("SecondMiddleware::after()"); // Mutate the Hyper Response at convenience // and send it back to other middlewares on the chain @@ -89,17 +89,15 @@ async fn main() -> Result { root: std::env::current_dir().unwrap(), }; - // 1. Create a custom middleware chain - let mut handler = Chain::new(Application { opts }); - - // 2. Plug in some custom middlewares - handler.link_before(FirstMiddleware {}); - handler.link_after(SecondMiddleware {}); + // 1. Create a custom middleware chain and plug in some custom middlewares + let mut middlewares = Middlewares::new(Application { opts }); + middlewares.link_before(FirstMiddleware {}); + middlewares.link_after(SecondMiddleware {}); - // 3. Create a Hyper service and set the current handler with its middlewares - let service = Service::new(handler); + // 2. Create a Hyper service and set the current handler with its middlewares + let service = Service::new(middlewares); - // 4. Finally just run server using the service already created + // 3. Finally just run server using the service already created let addr = ([127, 0, 0, 1], 8787).into(); let server = Server::bind(&addr).serve(service); diff --git a/src/error/mod.rs b/src/error/mod.rs index 95e4a50..08183be 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -1,8 +1,8 @@ //! The custom error module. //! -//! This module provides a custom [`Error`][`super::Error`] type with HTTP Status functionality as well as useful macros. -//! The `Error` type implements other several common error types -//! to ease conversions while consuming the input value via the [`From`] trait. +//! This module provides a custom [`Error`][`super::Error`] type with HTTP Status functionality as well as useful [`macros`]. +//! The `Error` type implements other several common error types as well +//! to ease conversion while consuming the input value via the [`From`] trait. //! //! Additionally, when used in HTTP contexts, the `Error` type can be associated to an [HTTP Status Code][`hyper::StatusCode`]. //! via the [`Error::with_status`][`super::Error::with_status`] method. @@ -10,7 +10,7 @@ //! a. Construct an [`Error`][`super::Error`] from [`hyper::Error`], [`std::io::Error`], [`anyhow::Error`] or an string. //! //! ```rust -//! use hyper_middleware::error +//! use hyper_middleware::{Error, error}; //! //! let err = Error::from("some error type or string"); //! // Or using a shortcut macro @@ -21,7 +21,7 @@ //! //! ```rust //! use hyper::StatusCode; -//! use hyper_middleware::error +//! use hyper_middleware::{error, http_error_unauthorized}; //! //! let err = error!("user or password does not match").with_status(StatusCode::UNAUTHORIZED); //! // Or using a shortcut macro @@ -33,9 +33,14 @@ use hyper::StatusCode; use std::fmt; use thiserror::Error as ThisError; +/// Macros that provide several facilities for working with HTTP response errors or error casting. pub mod macros; +/// `Result` +/// +/// An alias of [anyhow::Result][`anyhow::Result`] with defaults. pub type Result = anyhow::Result; + pub use anyhow::Context; /// Represents an HTTP Error. diff --git a/src/http.rs b/src/http.rs index 5916b12..573ed3f 100644 --- a/src/http.rs +++ b/src/http.rs @@ -3,8 +3,8 @@ /// A [`hyper::Body`] type alias. pub type Body = hyper::Body; -/// A [`hyper::Request`] type alias. +/// A [`hyper::Request`] type alias with defaults. pub type Request = hyper::Request; -/// A [`hyper::Response`] type alias. +/// A [`hyper::Response`] type alias with defaults. pub type Response = hyper::Response; diff --git a/src/lib.rs b/src/lib.rs index 2408e81..42a112d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,9 @@ -// #![deny(missing_docs)] +#![deny(missing_docs)] +#![forbid(unsafe_code)] +#![deny(warnings)] +#![deny(rust_2018_idioms)] +#![deny(dead_code)] +#![cfg_attr(docsrs, feature(doc_cfg))] //! # hyper_middleware //! @@ -10,6 +15,10 @@ //! - Compact [Middleware & Handler System][`middleware`] inspired by [The Iron Framework](https://github.com/iron/iron). //! - Simple [Hyper Service][`hyper::service::Service`] with [Remote Address][`hyper::server::conn::AddrStream`] access. //! - Convenient [`Error`] and [`Result`] types powered by [anyhow](https://github.com/dtolnay/anyhow). +//! - `Async` support via [async-trait](https://github.com/dtolnay/async-trait). +//! - Macros to facilitate HTTP response errors or error casting. +//! +//! Check it out [`middleware`] module for more details. //! pub mod error; @@ -18,10 +27,12 @@ pub mod middleware; pub mod remote_addr; pub mod service; -pub use async_recursion::*; -pub use async_trait::*; pub use error::{Context, Error, Result}; pub use http::*; pub use middleware::*; pub use remote_addr::*; pub use service::*; + +// Re-export crates +pub use async_recursion::*; +pub use async_trait::*; diff --git a/src/middleware.rs b/src/middleware.rs index c0da3ad..f205dac 100644 --- a/src/middleware.rs +++ b/src/middleware.rs @@ -16,11 +16,16 @@ //! Here's an example of a `Handler`: //! //! ```rust -//! use hyper_middleware::{Request, Response, Result}; +//! use hyper_middleware::{async_trait, Handler, Request, Response, Result, Body}; //! -//! fn hello_handler(req: &mut Request) -> Result { -//! Ok(Response::builder().body(Body::from("¡Hola!")).unwrap()) -//! }; +//! struct Application {} +//! +//! #[async_trait] +//! impl Handler for Application { +//! async fn handle(&self, req: &mut Request) -> Result { +//! Ok(Response::builder().body(Body::from("¡Hola!")).unwrap()) +//! } +//! } //! ``` //! //! # Middleware @@ -47,26 +52,33 @@ //! //! ## Defining the middleware pipeline //! -//! A `Chain` is a `Handler` that wraps another `Handler`. It is used to attach +//! the `Middlewares` chain is a `Handler` that wraps another `Handler`. It is used to attach //! middleware to the wrapped `Handler` using a `link` method corresponding to //! each type of middleware. A sample middleware pipeline is shown below: //! //! ```rust //! use hyper::Server; -//! use hyper_middleware::{BeforeMiddleware, Body, Chain, Request, Response, Result, Service}; -//! -//! fn hello_handler(_req: &mut Request) -> Result { -//! let mut resp = Response::new(Body::from("¡Hola!")); -//! resp.headers_mut().insert( -//! header::CONTENT_TYPE, -//! "text/html; charset=utf-8".parse().unwrap(), -//! ); -//! Ok(resp) +//! use hyper_middleware::{async_trait, Handler, BeforeMiddleware, Body, Middlewares, Request, Response, Result, Service}; +//! +//! struct Application {} +//! +//! #[async_trait] +//! impl Handler for Application { +//! async fn handle(&self, req: &mut Request) -> Result { +//! let mut resp = Response::new(Body::from("¡Hola!")); +//! resp.headers_mut().insert( +//! hyper::header::CONTENT_TYPE, +//! "text/html; charset=utf-8".parse().unwrap(), +//! ); +//! Ok(resp) +//! } //! } //! //! struct RequestLoggingMiddleware {} +//! +//! #[async_trait] //! impl BeforeMiddleware for RequestLoggingMiddleware { -//! fn before(&self, req: &mut Request) -> Result { +//! async fn before(&self, req: &mut Request) -> Result { //! println!("{:?}", req); //! Ok(()) //! } @@ -74,16 +86,16 @@ //! //! #[tokio::main(flavor = "multi_thread")] //! async fn main() -> Result { -//! let mut chain = Chain::new(hello_handler); +//! let mut middlewares = Middlewares::new(Application {}); //! // Plug in the custom middleware(s) -//! chain.link_before(RequestLoggingMiddleware {}); +//! middlewares.link_before(RequestLoggingMiddleware {}); //! -//! let addr = ([127, 0, 0, 1], 8787).into(); -//! let service = Service::new(chain); +//! let addr = ([127, 0, 0, 1], 8080).into(); +//! let service = Service::new(middlewares); //! let server = Server::bind(&addr).serve(service); //! println!("Listening on http://{}", addr); //! -//! server.await?; +//! // server.await?; //! //! Ok(()) //! } @@ -153,7 +165,7 @@ use std::sync::Arc; use crate::{Error, Request, Response, Result}; #[async_trait] -/// `Handler`s are responsible for handling requests by creating `Response`s from `Request`s. +/// `Handler`s are responsible for handling requests by creating `Response`s from those `Request`s. pub trait Handler: Send + Sync + 'static { /// Produce a `Response` from a Request, with the possibility of error. async fn handle(&self, req: &mut Request) -> Result; @@ -177,7 +189,7 @@ impl Handler for Box { } #[async_trait] -/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Chain. +/// `BeforeMiddleware` are fired before a `Handler` is called inside of a Middlewares. /// /// `BeforeMiddleware` are responsible for doing request pre-processing that requires /// the ability to change control-flow, such as authorization middleware, or for editing @@ -204,13 +216,13 @@ pub trait BeforeMiddleware: Send + Sync + 'static { } #[async_trait] -/// `AfterMiddleware` are fired after a `Handler` is called inside of a `Chain`. +/// `AfterMiddleware` are fired after a `Handler` is called inside of the `Middlewares` chain. /// /// `AfterMiddleware` receive both a `Request` and a `Response` and are responsible for doing /// any response post-processing. /// /// `AfterMiddleware` should *not* overwrite the contents of a `Response`. In -/// the common case, a complete response is generated by the Chain's `Handler` and +/// the common case, a complete response is generated by the Middlewares's `Handler` and /// `AfterMiddleware` simply do post-processing of that Response, such as /// adding headers or logging. pub trait AfterMiddleware: Send + Sync + 'static { @@ -229,19 +241,19 @@ pub trait AfterMiddleware: Send + Sync + 'static { } #[async_trait(?Send)] -/// `AroundMiddleware` are used to wrap and replace the `Handler` in a `Chain`. +/// `AroundMiddleware` are used to wrap and replace the `Handler` in the `Middlewares` chain. /// /// `AroundMiddleware` produce `Handler`s through their `around` method, which is -/// called once on insertion into a `Chain` or can be called manually outside of a -/// `Chain`. +/// called once on insertion into the `Middlewares` chain or can be called manually outside of a +/// `Middlewares` chain. pub trait AroundMiddleware { /// Produce a `Handler` from this `AroundMiddleware` given another `Handler`. /// /// Usually this means wrapping the handler and editing the `Request` on the /// way in and the `Response` on the way out. /// - /// This is called only once, when an `AroundMiddleware` is added to a `Chain` - /// using `Chain::around`, it is passed the `Chain`'s current `Handler`. + /// This is called only once, when an `AroundMiddleware` is added to the `Middlewares` chain + /// using `Middlewares::around`, it is passed the `Middlewares` chain's current `Handler`. async fn around(self, handler: Box) -> Box; } @@ -250,7 +262,7 @@ pub trait AroundMiddleware { /// This is a canonical implementation of Iron's middleware system, /// but Iron's infrastructure is flexible enough to allow alternate /// systems. -pub struct Chain { +pub struct Middlewares { befores: Vec>, afters: Vec>, @@ -258,9 +270,12 @@ pub struct Chain { handler: Option>, } -impl Chain { - /// Construct a new `Chain` from a `Handler`. - pub fn new(handler: H) -> Self { +impl Middlewares { + /// Construct a new middleware chain from a `Handler`. + pub fn new(handler: H) -> Self + where + H: Handler, + { Self { befores: vec![], afters: vec![], @@ -272,7 +287,7 @@ impl Chain { /// /// Middleware that have a Before and After piece should have a constructor /// which returns both as a tuple, so it can be passed directly to link. - pub fn link(&mut self, link: (B, A)) -> &mut Chain + pub fn link(&mut self, link: (B, A)) -> &mut Middlewares where A: AfterMiddleware, B: BeforeMiddleware, @@ -285,9 +300,9 @@ impl Chain { self } - /// Link a `BeforeMiddleware` to the `Chain`, after all previously linked + /// Link a `BeforeMiddleware` to the `Middlewares` chain, after all previously linked /// `BeforeMiddleware`s. - pub fn link_before(&mut self, before: B) -> &mut Chain + pub fn link_before(&mut self, before: B) -> &mut Middlewares where B: BeforeMiddleware, { @@ -296,9 +311,9 @@ impl Chain { self } - /// Link a `AfterMiddleware` to the `Chain`, after all previously linked + /// Link a `AfterMiddleware` to the `Middlewares` chain, after all previously linked /// `AfterMiddleware`s. - pub fn link_after(&mut self, after: A) -> &mut Chain + pub fn link_after(&mut self, after: A) -> &mut Middlewares where A: AfterMiddleware, { @@ -307,8 +322,8 @@ impl Chain { self } - /// Apply an `AroundMiddleware` to the `Handler` in this `Chain`. - pub async fn link_around(&mut self, around: A) -> &mut Chain + /// Apply an `AroundMiddleware` to the `Handler` in this `Middlewares` chain. + pub async fn link_around(&mut self, around: A) -> &mut Middlewares where A: AroundMiddleware, { @@ -320,7 +335,7 @@ impl Chain { } #[async_trait] -impl Handler for Chain { +impl Handler for Middlewares { async fn handle(&self, req: &mut Request) -> Result { // Kick off at befores, which will continue into handler // then afters. @@ -328,7 +343,7 @@ impl Handler for Chain { } } -impl Chain { +impl Middlewares { #[async_recursion] // Enter the error flow from a before middleware, starting // at the passed index. diff --git a/src/service.rs b/src/service.rs index 4dbb369..771851f 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,19 +1,21 @@ //! The Hyper service module. //! //! It provides a [Hyper Service][`hyper::service::Service`] implementation intended to work with -//! the [Hyper Server Builder][`hyper::server::Builder`]. +//! the `hyper::server::Builder`. //! -//! The service allows to bind a [`Chain`][`super::Chain`] of middlewares. +//! The service allows to bind a [`Middlewares`][`super::Middlewares`] of middlewares. //! //! ## Example //! //! ```rust //! use hyper::Server; //! use hyper_middleware::{ -//! Body, Handler, Request, Response, Result, Service +//! async_trait, Body, Handler, Request, Response, Middlewares, Result, Service, //! }; //! //! struct Application {} +//! +//! #[async_trait] //! impl Handler for Application { //! async fn handle(&self, _req: &mut Request) -> Result { //! // Create a response and send it back to the middlewares chain @@ -23,16 +25,17 @@ //! //! #[tokio::main(flavor = "multi_thread")] //! async fn main() -> Result { -//! let mut my_handler = Chain::new(Application {}); +//! let mut middlewares = Middlewares::new(Application {}); //! -//! let my_service = Service::new(my_handler); +//! let service = Service::new(middlewares); //! -//! let addr = ([127, 0, 0, 1], 8787).into(); -//! let server = Server::bind(&addr).serve(my_service); +//! let addr = ([127, 0, 0, 1], 8087).into(); +//! let server = Server::bind(&addr).serve(service); //! //! println!("Listening on http://{}", addr); //! -//! server.await?; +//! // server.await?; +//! //! Ok(()) //! } //! ```