Cookbook / Getting started

Routing

Path parameters, wildcards, route groups, and how conflicts are settled.

Routes use :name for a single segment and *name for the rest of the path. Static segments always beat parameters, so /users/new is never swallowed by /users/:id. Group related routes in a Router and mount it under a prefix.

src/main.rs
use axeon::{Router, Server};

fn main() {
    let mut app = Server::new();

    app.get("/", |_req| async { "home" })
        .post("/users", |_req| async { (201, "created") })
        .get("/users/new", |_req| async { "the sign-up form" })
        .get("/users/:id", |req| async move {
            format!("user {}", req.params()["id"])
        })
        .get("/files/*path", |req| async move {
            format!("file {}", req.params()["path"])
        });

    // A group of routes, mounted under /api/v1.
    let mut v1 = Router::new();
    v1.get("/status", |_req| async { "ok" });
    v1.get("/teams/:team/members/:member", |req| async move {
        let params = req.params();
        format!("{} / {}", params["team"], params["member"])
    });
    app.mount("/api/v1", v1);

    app.listen("127.0.0.1:3000").expect("server failed to start");
}
Terminal
curl http://127.0.0.1:3000/users/new          # the sign-up form
curl http://127.0.0.1:3000/users/42           # user 42
curl http://127.0.0.1:3000/files/a/b/c.txt    # file a/b/c.txt
curl http://127.0.0.1:3000/api/v1/status      # ok
curl -i -X DELETE http://127.0.0.1:3000/      # 405 with an Allow header

Notes#

  • HEAD and OPTIONS are answered automatically. A known path with the wrong method gets 405 Method Not Allowed and an Allow header.
  • Routes that can never be told apart, such as /users/:id and /users/:name, are reported when the server starts rather than at request time.
  • Routing time does not grow with the number of routes.
  • Inside a handler, req.matched_path() gives you the pattern (/users/:id), which is the right label for metrics.