Macro goohttp::router

source ·
macro_rules! router {
    {
        $group_id:tt {
            $ (
                $route:tt
                $ (
                    ,
                    $request_type:tt
                    $(
                        ,
                        $parameter:literal
                    ) *
                ) ?
            ); *
            $( ; )?
        }
    } => { ... };
}
Expand description

An easier way to create an axum router.

Usage

For this example, we will look at a simple frontend setup with the following file structure:

src
├── frontend
│   ├── api
│   │   ├── mod.rs
│   │   ├── say_hello_caller_sender.rs
│   │   └── say_hello.rs
│   ├── index.rs
│   └── mod.rs
└── main.rs

We start at our entry point for the application:
src/main.rs

use frontend::serve_frontend;

mod frontend;

fn main() {
    let frontend_router = serve_frontend();     // this function got generated by this macro

    // ... code using the frontend_router
}

Next, we define our root router:
src/frontend/mod.rs

use goohttp::router;

// First we define the route `/` which will be accessible via the `get` method
// And then link to another router group at `/api`
router! {
    serve_frontend {    // the name of this router
        index, get;
        api
    }
}

Leaving the above code as it is will result in a compiler error because the modules and their associated functions index and api could not be found. So we need to create these modules as well.
First, we define our route index:
src/frontend/index.rs

use goohttp::axum::response::IntoResponse;

pub async fn index() -> impl IntoResponse {
    "Hello World!".into_response();
}

Now all we need to do is define our router group at /api:
src/frontend/api/mod.rs

use goohttp::router;

// Our api will have two routes both taking some arguments, as indicated by the additional strings starting with a column.
// Since this macro is using the axum router internally, their rules apply, when defining arguments to routes.
router! {
    api {
        // This will, when combined with the root router, result in the route `/api/say_hello/{any argument here}`
        say_hello, get, ":caller";
        // And this in the route `/api/say_hello_caller_sender/{any argument here}/{any argument here}`
        say_hello_caller_sender, get, ":caller", ":sender"
    }
}

All that remains is to define the two remaining routes:
src/frontend/api/say_hello.rs

use goohttp::axum::{
    extract::Path,
    response::IntoResponse,
};

pub async fn say_hello(Path(caller): Path<String>) -> impl IntoResponse {
    format!("said hello from {caller}").into_response()
}

src/frontend/api/say_hello_caller_sender.rs

use goohttp::axum::{
    extract::Path,
    response::IntoResponse,
};

pub async fn say_hello_caller_sender(
    Path((caller, sender)): Path<(String, String)>
) -> impl IntoResponse {
    format!("said hello from {caller} to {sender}").into_response()
}

As a result, we will have the following routes defined for our frontend_router:

  • /
  • /api/say_hello/{any argument here}
  • /api/say_hello_caller_sender/{any argument here}/{any argument here}