== Contextual Routing This issue has previously been adressed as "dynamic routing". // Problem can be split in two, // TODO In Axum, routers can be configured using a fluid-like API #footnote[Term borrowed from C\# and OOP]. #box[```rs #[tokio::main] async fn main() { let app = Router::new() .route("/", get(root)) // .route("/posts", get(get_posts)) .route("/posts/:post_id", get(get_post_by_id)) .route("/posts/:post_id/discussions/+thread_ids", get(get_posts_threads)); todo!("Actually listen") } async fn root() { todo!() } async fn get_post_by_id(Path(post_id): Path) -> impl IntoResponse { todo!() } async fn get_posts_threads(Path(post_id): Path, Path(discussion_thread_ids): Path) -> impl IntoResponse { let discussion_thread_ids = discussion_thread_ids.split("/"); todo!() } ```] As it can be seen, a parameter can be extracted from the URL path by using `/:some_name` and can be placed as any infix of the URL: at the beginning, in the middle, or the end. However, as the path is split by slash characters (`/`), the extracted part must not contain slashes and hence can only be (up to) one part of the path. Longer parts of the request can be obtained using `+some_name` and can only be placed as a postfix of the URL, but not other types of infixes. This can be used to obtain the remaining path of the request. === Problem Description + The API to implement e.g. has the concept of mount points (similar to how filesystems can be mounted on UNIX-like systems). Mount points can contain multiple slashes. For example `/v1/some/mount/point/data/some/path/secret` may consist of a mount point `some/mount/point` and further, following routes of the mapped secret engine. //TODO In this example, `/data` is related to the Key-Value engine and `/some/path/secret` specifies a path within the secret engine instance mounted at the mount point. This implies a significant problem: How to determinate what part of the URL displays a mount point, where it is not certan, what the postfix of the URL will be (this problem follows). + Another problem is that based on the mount point, the request must be processed by the applicable secret engine. Based on context, stored on the DBMS, the request must be passed to the secret engine along with the determinated mount point. === Solution Secret Engines have their dedicated router. The main router has an instance of these routers along with the database pool wrapped within a struct in its state. The router instances have a reference to the database pool, which is internally wrapped by an Atomic Reference Counter (`Arc`). Upon a requst, the remaining path is obtained (via `/+mount_path`). Then, the path is looked up at the database, also requsting the engine type. If not found, the last last slash character and the following string is removed and looked up again. This is repeated, until the path either is found or has a length of zero, rejecting the request as "404 Not Found". If found, the router is called with the request and mount path is given to the router as an "Extension". The `call` #link("https://docs.rs/tower/0.4.13/tower/trait.Service.html#tymethod.call")[(link)] function which Axum routers inherit from the Tower crate, allows to hand the request over to engine's router.