routerify/routerify

A lightweight, idiomatic, composable and modular router implementation with middleware support for the Rust HTTP library hyper.rs

Rust

392

220 commits

updated Feb 22, 2024

See the code

README

Github Actions Status crates.io Documentation Contributors MIT

Routerify

Routerify provides a lightweight, idiomatic, composable and modular router implementation with middleware support for the Rust HTTP library hyper.

Routerify's core features:

To generate a quick server app using Routerify and hyper, please check out hyper-routerify-server-template.

Compiler support: requires rustc 1.48+

Benchmarks

FrameworkLanguageRequests/sec
hyper v0.14Rust 1.50.0144,583
routerify v2.0.0 with hyper v0.14Rust 1.50.0144,621
actix-web v3Rust 1.50.0131,292
warp v0.3Rust 1.50.0145,362
go-httprouter, branch masterGo 1.16130,662
Rocket, branch masterRust 1.50.0130,045

For more info, please visit Benchmarks.

Install

Add this to your Cargo.toml file:

[dependencies]
routerify = "3"
hyper = "0.14"
tokio = { version = "1", features = ["full"] }

Basic Example

A simple example using Routerify with hyper would look like the following:

use hyper::{Body, Request, Response, Server, StatusCode};
// Import the routerify prelude traits.
use routerify::prelude::*;
use routerify::{Middleware, Router, RouterService, RequestInfo};
use std::{convert::Infallible, net::SocketAddr};

// Define an app state to share it across the route handlers and middlewares.
struct State(u64);

// A handler for "/" page.
async fn home_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    // Access the app state.
    let state = req.data::<State>().unwrap();
    println!("State value: {}", state.0);

    Ok(Response::new(Body::from("Home page")))
}

// A handler for "/users/:userId" page.
async fn user_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    let user_id = req.param("userId").unwrap();
    Ok(Response::new(Body::from(format!("Hello {}", user_id))))
}

// A middleware which logs an http request.
async fn logger(req: Request<Body>) -> Result<Request<Body>, Infallible> {
    println!("{} {} {}", req.remote_addr(), req.method(), req.uri().path());
    Ok(req)
}

// Define an error handler function which will accept the `routerify::Error`
// and the request information and generates an appropriate response.
async fn error_handler(err: routerify::RouteError, _: RequestInfo) -> Response<Body> {
    eprintln!("{}", err);
    Response::builder()
        .status(StatusCode::INTERNAL_SERVER_ERROR)
        .body(Body::from(format!("Something went wrong: {}", err)))
        .unwrap()
}

// Create a `Router<Body, Infallible>` for response body type `hyper::Body`
// and for handler error type `Infallible`.
fn router() -> Router<Body, Infallible> {
    // Create a router and specify the logger middleware and the handlers.
    // Here, "Middleware::pre" means we're adding a pre middleware which will be executed
    // before any route handlers.
    Router::builder()
        // Specify the state data which will be available to every route handlers,
        // error handler and middlewares.
        .data(State(100))
        .middleware(Middleware::pre(logger))
        .get("/", home_handler)
        .get("/users/:userId", user_handler)
        .err_handler_with_info(error_handler)
        .build()
        .unwrap()
}

#[tokio::main]
async fn main() {
    let router = router();

    // Create a Service from the router above to handle incoming requests.
    let service = RouterService::new(router).unwrap();

    // The address on which the server will be listening.
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    // Create a server by passing the created service to `.serve` method.
    let server = Server::bind(&addr).serve(service);

    println!("App is running on: {}", addr);
    if let Err(err) = server.await {
        eprintln!("Server error: {}", err);
   }
}

Documentation

Please visit: Docs for an exhaustive documentation.

Examples

The examples.

Contributing

Your PRs and suggestions are always welcome.

cargo
http
hyper
hyper-rs
middleware
router
routerify
routing
rust

routerify/routerify

A lightweight, idiomatic, composable and modular router implementation with middleware support for the Rust HTTP library hyper.rs

Rust

392

220 commits

updated Feb 22, 2024

See the code

README

Github Actions Status crates.io Documentation Contributors MIT

Routerify

Routerify provides a lightweight, idiomatic, composable and modular router implementation with middleware support for the Rust HTTP library hyper.

Routerify's core features:

To generate a quick server app using Routerify and hyper, please check out hyper-routerify-server-template.

Compiler support: requires rustc 1.48+

Benchmarks

FrameworkLanguageRequests/sec
hyper v0.14Rust 1.50.0144,583
routerify v2.0.0 with hyper v0.14Rust 1.50.0144,621
actix-web v3Rust 1.50.0131,292
warp v0.3Rust 1.50.0145,362
go-httprouter, branch masterGo 1.16130,662
Rocket, branch masterRust 1.50.0130,045

For more info, please visit Benchmarks.

Install

Add this to your Cargo.toml file:

[dependencies]
routerify = "3"
hyper = "0.14"
tokio = { version = "1", features = ["full"] }

Basic Example

A simple example using Routerify with hyper would look like the following:

use hyper::{Body, Request, Response, Server, StatusCode};
// Import the routerify prelude traits.
use routerify::prelude::*;
use routerify::{Middleware, Router, RouterService, RequestInfo};
use std::{convert::Infallible, net::SocketAddr};

// Define an app state to share it across the route handlers and middlewares.
struct State(u64);

// A handler for "/" page.
async fn home_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    // Access the app state.
    let state = req.data::<State>().unwrap();
    println!("State value: {}", state.0);

    Ok(Response::new(Body::from("Home page")))
}

// A handler for "/users/:userId" page.
async fn user_handler(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    let user_id = req.param("userId").unwrap();
    Ok(Response::new(Body::from(format!("Hello {}", user_id))))
}

// A middleware which logs an http request.
async fn logger(req: Request<Body>) -> Result<Request<Body>, Infallible> {
    println!("{} {} {}", req.remote_addr(), req.method(), req.uri().path());
    Ok(req)
}

// Define an error handler function which will accept the `routerify::Error`
// and the request information and generates an appropriate response.
async fn error_handler(err: routerify::RouteError, _: RequestInfo) -> Response<Body> {
    eprintln!("{}", err);
    Response::builder()
        .status(StatusCode::INTERNAL_SERVER_ERROR)
        .body(Body::from(format!("Something went wrong: {}", err)))
        .unwrap()
}

// Create a `Router<Body, Infallible>` for response body type `hyper::Body`
// and for handler error type `Infallible`.
fn router() -> Router<Body, Infallible> {
    // Create a router and specify the logger middleware and the handlers.
    // Here, "Middleware::pre" means we're adding a pre middleware which will be executed
    // before any route handlers.
    Router::builder()
        // Specify the state data which will be available to every route handlers,
        // error handler and middlewares.
        .data(State(100))
        .middleware(Middleware::pre(logger))
        .get("/", home_handler)
        .get("/users/:userId", user_handler)
        .err_handler_with_info(error_handler)
        .build()
        .unwrap()
}

#[tokio::main]
async fn main() {
    let router = router();

    // Create a Service from the router above to handle incoming requests.
    let service = RouterService::new(router).unwrap();

    // The address on which the server will be listening.
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    // Create a server by passing the created service to `.serve` method.
    let server = Server::bind(&addr).serve(service);

    println!("App is running on: {}", addr);
    if let Err(err) = server.await {
        eprintln!("Server error: {}", err);
   }
}

Documentation

Please visit: Docs for an exhaustive documentation.

Examples

The examples.

Contributing

Your PRs and suggestions are always welcome.

cargo
http
hyper
hyper-rs
middleware
router
routerify
routing
rust

Project health

Overall

3.0/10

Maintained

0/10

Code review

2/10
OpenSSF Scorecard

crates.io

Latest release

3.0.0 · Dec 24, 2021

Releases this year

0

Significant stargazers

Arpad Borsos

481 followers · starred Jan 2021

Michael Goulet

683 followers · starred Dec 2021

Raminder Singh

84 followers · starred Jun 2021

David Barsky

378 followers · starred May 2020