Hyper Middleware

A compact HTTP middleware and handler system for Hyper 0.14.x
.
NOTE: This crate is still under active development.
Features
- Compact Middleware and Handler System inspired by The Iron Framework.
- Simple Hyper Service with convenient Remote Address access.
- Convenient
Error
and Result
types powered by anyhow.
Async
support via async-trait.
- Macros to facilitate HTTP response errors or error casting.
Example
examples/server.rs
use hyper::{header, Server, StatusCode};
use hyper_middleware::{
async_trait, AfterMiddleware, BeforeMiddleware, Body, Error, Handler, Middlewares, Request,
Response, Result, Service,
};
use std::{net::SocketAddr, path::PathBuf};
struct Config {
pub root: PathBuf,
}
struct Application {
opts: Config,
}
#[async_trait]
impl Handler for Application {
async fn handle(&self, req: &mut Request) -> Result<Response> {
println!("Application::handle() - URI Path: {}", req.uri().path());
println!(
"Application::handle() - Config Root: {}",
self.opts.root.display()
);
let remote_addr = req.extensions().get::<SocketAddr>().unwrap();
println!("Application::handle() - Remote Addr: {}", remote_addr);
Ok(Response::new(Body::from("¡Hola!")))
}
}
struct FirstMiddleware {}
#[async_trait]
impl BeforeMiddleware for FirstMiddleware {
async fn before(&self, req: &mut Request) -> Result {
println!("FirstMiddleware::before()");
println!("FirstMiddleware::before() - URI Path: {}", req.uri().path());
Ok(())
}
async fn catch(&self, _: &mut Request, err: Error) -> Result {
Err(err)
}
}
struct SecondMiddleware {}
#[async_trait]
impl AfterMiddleware for SecondMiddleware {
async fn after(&self, _: &mut Request, mut res: Response) -> Result<Response> {
println!("SecondMiddleware::after()");
res.headers_mut().insert(
header::CONTENT_TYPE,
"text/html; charset=utf-8".parse().unwrap(),
);
Ok(res)
}
async fn catch(&self, _: &mut Request, err: Error) -> Result<Response> {
Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from(err.to_string()))
.unwrap())
}
}
#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result {
let opts = Config {
root: std::env::current_dir().unwrap(),
};
let mut middlewares = Middlewares::new(Application { opts });
middlewares.link_before(FirstMiddleware {});
middlewares.link_after(SecondMiddleware {});
let service = Service::new(middlewares);
let addr = ([127, 0, 0, 1], 8787).into();
let server = Server::bind(&addr).serve(service);
println!("Listening on http://{}", addr);
server.await?;
Ok(())
}
To run the example just type:
cargo run --example server
Contributions
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in current work by you, as defined in the Apache-2.0 license, shall be dual licensed as described below, without any additional terms or conditions.
Feel free to send some Pull request or file an issue.
License
This work is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).
© 2022-present Jose Quintana