Routing
Route definition
Routes, like all Pavex components, are defined using attributes.
use pavex::get;
use pavex::http::StatusCode;
/// Respond with a `200 OK` status code to indicate that the server is alive
/// and ready to accept new requests.
#[get(path = "/ping")] // (1)!
pub fn ping() -> StatusCode {
StatusCode::OK
}
#[pavex::get]defines a route that responds toGETrequests for the specified path.
Route registration
It's not enough to define a route, you also need to register it with the Blueprint.
That's taken care of by the .routes() invocation:
// [...]
use pavex::{Blueprint, blueprint::from};
/// The main blueprint, defining all the components used in this API.
pub fn blueprint() -> Blueprint {
// [...]
bp.prefix("/api").routes(from![crate]);
// [...]
}
It's registering, in bulk, all the routes defined in the current crate, including our ping. Since it introduces a prefix,
the final route is GET /api/ping rather than GET /ping.
Add a new route
The ping function is fairly boring: it doesn't take any arguments, and it always returns the same response.
Let's spice things up with a new route: GET /api/greet/{name}.
Its path includes a dynamic path parameter (name) and we want it to return a success response with Hello, {name} as its body.
Create a new greet module under routes to hold the route definition:
use pavex::{Response, get};
#[get(path = "/greet/{name}")] // (1)!
pub fn greet() -> Response {
todo!()
}
- Dynamic path parameters are enclosed in curly braces (
{}).
The body of the GET /api/greet/{name} handler is stubbed out with todo!() for now, but we'll fix that soon enough.
Extract path parameters
To access the name route parameter from your new handler you must use the PathParams extractor:
use pavex::{Response, get, request::path::PathParams};
#[PathParams]
pub struct GreetParams {
pub name: String, // (1)!
}
#[get(path = "/greet/{name}")]
pub fn greet(params: PathParams<GreetParams> /* (2)! */) -> Response {
let GreetParams { name } /* (3)! */ = params.0;
Response::ok() // (4)!
.set_typed_body(format!("Hello, {name}!")) // (5)!
}
- The name of the field must match the name of the route parameter as it appears in the path we registered with
the
Blueprint. - The
PathParamsextractor is generic over the type of the path parameters. In this case, we're using theGreetParamstype we just defined. - This is an example of Rust's destructuring syntax.
Responsehas a convenient constructor for each HTTP status code:Response::okstarts building aResponsewith a200 OKstatus code.set_typed_bodysets the body of the response and automatically infers a suitable value for theContent-Typeheader based on the response body type.
Does it work? Only one way to find out! Re-launch the application and issue a new request: (1)
- Remember to use
cargo px runinstead ofcargo run!
You should see Hello, Ursula! in your terminal if everything went well.