Struct cataclysm::Branch[][src]

pub struct Branch<T> { /* fields omitted */ }
Expand description

Main cataclysm structure for route handling

Branches are cataclysm’s main building block. It is a really simple pattern matching system, with the following priorities. They are named branches to avoid conflict with the Branch extractor.

  1. Exact matching
  2. Pattern matching
  3. Default branches (a.k.a, variable handling in branches)

In the case of exact matching, the path constructor is pretty straight forward

let branch: Branch<()> = Branch::new("/hello/world");

Pattern matching is a bit more complex

// matches any route that starts with `/hello/` and then words of 3 or 4 letters, no numbers
let branch: Branch<()> = Branch::new("/hello/{regex:^[A-Za-z\\d]{3,4}$}");

Last but not least, we have variable detection, with no regex

// matches any route that contains "/hello/{:variable}"
let branch: Branch<()> = Branch::new("/hello/{:variable}");

Implementations

Creates a new branch

let branch: Branch<()> = Branch::new("/hello/world");

Adds a callback to a branch

This function is the main building block for callbacks in the branch. A MethodHandler consists of a Method, and a callback function. Se the Method structure to see how to construct them.

// Example index function
async fn index() -> Response {
    Response::ok().body("hello")
}

// Branch that will reply go a get method in `/scope`
let branch: Branch<()> = Branch::new("/scope").with(Method::Get.to(index));

Adds a default method responder, in case no specific handler is found for the requested method.

By default, unmatched methods reply with a 405 Method Not Allowed, but this function allows override of such behaviour.

let branch: Branch<()> = Branch::new("/").with(Method::Get.to(|| async {
    Response::ok().body("Supported!")
})).unmatched_method_to(|| async {
    Response::ok().body("Unsupported, please try with GET")
});

Adds a default callback, in case of no nested matching.

// This branch will reply in any of `/hello`, `/hello/world`, etc.
let branch: Branch<()> = Branch::new("/hello").defaults_to(|| async {
    Response::ok().body("Are you lost?")
});

Merges two branches from their bases, in case you find it useful

let branch_1: Branch<()> = Branch::new("/hello/world");
let branch_2 = Branch::new("/hallo/welt");
// Replies to both branches, in theory
let merged_branch = branch_1.merge(branch_2);

Please note that the caller has precedence over the callee, so in case of layers, the layers of the left hand side will have precedence, as well as the regex matches and the variable callback.

Nests one branch in the top node of the first one

The “top node” is defined as the one following the path given to the branch constructor.

let to_be_nested: Branch<()> = Branch::new("/world");
// This one will reply in `/hello/world`
let branch = Branch::new("/hello").nest(to_be_nested);

Adds a processing layer to the callbacks contained in this branch

A layer is what is commonly known as middleware. The passed layer methods act as a wrap to the core handling functions of this branch. It is important to note that layer functions have a very specific structure: each one receives a Request and a boxed Pipeline. The function must return a pinned boxed future. A Timing Layer/Middleware function is provided as an example.

use cataclysm::{Branch, Additional, Pipeline, http::{Request, Response, Method}};
use futures::future::FutureExt;
use std::sync::Arc;
 
let branch = Branch::new("/hello")
    .with(Method::Get.to(|| async {Response::ok().body("¡Hola!")}))
    .layer(|req: Request, pipeline: Box<Pipeline<()>>, ad: Arc<Additional<()>>| async {
        // Example of timing layer / middleware
        let now = std::time::Instant::now();
        // Execute the deeper layers of the pipeline, passing the request
        let response = pipeline.execute(req, ad).await;
        // Measure and print time
        let elapsed = now.elapsed().as_nanos();
        println!("Process time: {} ns", elapsed);
        // We return the request for further possible processing.
        response
    }.boxed()
);

Calling the function multiple times will wrap the preceeding layer (or core handlers), like an onion 🧅.

Trait Implementations

Formats the value using the given formatter. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

Converts the given value to a String. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.