2 unstable releases

0.2.0 Nov 18, 2019
0.1.0 Nov 5, 2019

#23 in #http-router

MIT license

23KB
334 lines

Pathmaker

Generalized routing for any HTTP library. Not too fancy.

Usage

To use this library, add the following to your Cargo.toml:

pathmaker = "0.1.0"

If you want to use it with a specific HTTP library, e.g. hyper, enable that feature:

hyper = "0.12"
pathmaker = { version = "0.1", features = ["hyper"] }

Then, in your code, construct a router:

extern crate hyper;
extern crate pathmaker;
extern crate failure;
extern crate futures;

use hyper::{Request, Response, Method, Body, Server};
use hyper::service::make_service_fn;
use hyper::header::CONTENT_LENGTH;
use pathmaker::hyper::Router;
use failure::Error;
use futures::prelude::*;

fn router() -> Router {
    let mut build = Router::build();
    build.get("/foo", |_, _| {
        let body = "Hello, world!";
        Box::new(futures::future::result(Response::builder()
            .header(CONTENT_LENGTH, body.len() as u64)
            .body(Body::from(body))
            .map_err(Error::from)
        ))
    });
    build.finish()
}

fn main() {
    let address = "0.0.0.0:8080".parse().unwrap();
    let server = Server::bind(&address)
        .serve(make_service_fn(|_| Ok::<_, hyper::Error>(router()))).map_err(|e| {
            eprintln!("error: {:?}", e);
        });
    // hyper::rt::run(server)
}

Query Parameters

Support for query parameters is allowed by using {} in the path:

// ...
fn router() -> Router {
    let mut build = Router::build();
    build.get("/foo", handler)
         .get("/hello/{}", hello_handler);
    build.finish()
}
// ...

Then, in the handler, you can access the first element of the second argument in order to get the result:

//...
fn hello_handler(_: Request<Body>, params: Vec<String>) -> Box<dyn Future<Item = Response<Body>, Error = Error> + Send> {
    let body = format!("Hello, {}!", params[0]);
    Box::new(futures::future::result(
        Response::builder()
            .header(CONTENT_LENGTH, body.len() as u64)
            .body(Body::from(body))
            .map_err(Error::from)
    ))
}
// ...

Query parameters can be filtered down by format:

  • {}, {:string} (the default): anything that isn't a / character is matched.
  • {:int}: a positive or negative number.
  • {:uint}: just a number, no sign allowed.
  • {:uuid}: a UUID, in 8-4-4-4-12 format.

More can be added if requested.

Route Evaluation

Routes are evaluated from top to bottom. The first route that matches is used.

Dependencies

~4.5–7MB
~129K SLoC