11 releases (5 breaking)

0.6.2 Aug 4, 2021
0.6.0 Jul 18, 2021

#8 in #http-router

MIT/Apache

22KB
155 lines

A simple request router

Designed to be wasm compatible, simple and small.

extern crate alloc;
use alloc::borrow::Cow;

use mimeograph_router::*;

/// A request could be an `http` crate Request, or a CloudFlare
/// worker Request. Here is a very simple request:
pub struct Request {
    path: String,
    method: String,
}

/// To use the router, implement `mimeograph_request::Request`
/// for the Request type that you are working with.
impl mimeograph_request::Request for Request {
    fn path(&self) -> Cow<'_, str> {
        Cow::Borrowed(&self.path)
    }
    fn method(&self) -> Cow<'_, str> {
        Cow::Borrowed(&self.method)
    }
}

/// A dummy Response type
pub struct Response {
    status: u32,
    body: String,
}

type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;

#[get("/hello")]
fn get_hello(request: Request) -> Result<Response> {
    Ok(Response {
        status: 200,
        body: String::from("world"),
    })
}

#[get("/greet/:name")]
fn get_greeting(request: Request, name: &str) -> Result<Response> {
    Ok(Response {
        status: 200,
        body: format!("Hello, {}!", name),
    })
}

// Wildcard segment
#[get("/foo/*/baz/:name")]
fn foo_baz_name(request: Request, name: &str) -> Result<Response> {
    Ok(Response {
        status: 200,
        body: format!("Hello, {}!", name),
    })
}

// Glob, matches everything after /page/, ie: /page/hello/world
#[get("/page/**")]
fn page_glob(request: Request) -> Result<Response> {
    Ok(Response {
        status: 200,
        body: String::from("Hello, World"),
    })
}

/// All verbs are supported:
/// get, put, post, delete, head, patch, options
#[post("/images")]
fn post_image(request: Request) -> Result<Response> {
    // handle request
    unimplemented!()
}

/// The entrypoint for handling a request
pub fn handle_request(request: Request) -> Response {
    // router![] creates a closure that iterates through
    // the handlers until one is matched, then it returns
    // the matched handler's response
    let routes = routes![get_hello, get_greeting, foo_baz_name, page_glob];

    match router(request, routes) {
        // Matched a route
        RouterResult::Handled(Ok(resp)) => resp,
        // There was an error
        RouterResult::Handled(Err(_err)) => todo!(),
        // No routes matched, request is passed back
        RouterResult::NotHandled(_request) => todo!(),
    }
}

Dependencies

~2MB
~41K SLoC