macro_rules! main {
    ($service_name:tt, $routes_fns:tt) => { ... };
    ($service_name:tt, $state_setup:tt, $routes_fns:tt) => { ... };
    ($service_name:tt, $state_setup:tt, $custom_setup:tt, $routes_fns:tt) => { ... };
}
Expand description

Begin here. A macro which constructs the equivalent of an async fn main() {}.

Automatically pulls in setup for preroll’s default and optional features.

This macro takes the following arguments:

service_name

The constant service name, staticly set in the service’s code.

An &'static str, e.g. "service-name".

state_setup (optional)

This is where server state can be set.

An async fn setup_state() -> preroll::SetupResult<State>, where State is anything which can be thread-safe. That is, the state must implement Send + Sync, (usually automatically), and must have the 'static lifetime (must be owned).

It is expected that State is some arbitrary custom type used by your service. preroll will wrap it in an Arc so that it can be shared.

This function must be async and must return a preroll::SetupResult. It is expected that setup could be anything and may need to await or error.

See tide::Server::with_state() for more on Tide server state.

custom_setup (optional) (advanced)

Advanced, custom setup with access to the full server struct. Prefer using routes_setup whenever possible.

An async fn custom_setup(server: Server<Arc<State>>) -> SetupResult<Server<Arc<State>>>, where State is the type returned from setup_state or else the unit () type.

routes_setup (one or more)

This is where routes should be set.

A fn setup_routes(server: &mut tide::Server<Arc<State>>), where State is the type returned from setup_state or else the unit () type. It is expected that only Tide route handlers are set in this function. It must not be async and must not error.

API Versioning

Any number of routes_setup functions can be provided, by use of VariadicRoutes, which will be API versioned as described below. Usually this is done by putting the routes in a Tuple, similar to just adding more arguments but wrapping the routes arguments in parenthesis: (routes_v1, routes_v2).

Preroll route setup functions are automatically namespaced under /api/v{N} where the {N} is the position of the routes setup function in preroll::main!’s arguments, starting at 1.

For example, preroll::main!("my-service", my_routes) will have my_routes mounted at /api/v1.

See tide::Server::at() for more on Tide server routing.

Basic Example

This will respond with "Hello World!" when a GET request is made to $HOST:$PORT/api/v1/hello-world.

use std::sync::Arc;

use tide::{Request, Route};

struct AppState {
    greeting: &'static str,
}

type AppRequest = Request<Arc<AppState>>;

async fn setup_app_state() -> preroll::SetupResult<AppState> {
    Ok(AppState {
        greeting: "Hello World!",
    })
}

fn setup_routes(mut server: Route<'_, Arc<AppState>>) {
    server
        .at("hello-world")
        .get(|req: AppRequest| async move {
            Ok(req.state().greeting)
        });
}

preroll::main!("hello-world", setup_app_state, setup_routes);

Full Example

With custom middleware and multiple api versions.

use std::sync::Arc;

use preroll::SetupResult;
use tide::{Request, Route, Server};

pub struct AppState {
    greeting: &'static str,
}

type AppRequest = Request<Arc<AppState>>;

async fn setup_app_state() -> preroll::SetupResult<AppState> {
    Ok(AppState {
        greeting: "Hello World!",
    })
}

pub async fn setup_custom(
   server: Server<Arc<AppState>>
) -> SetupResult<Server<Arc<AppState>>> {
   // Adjust `server` in whichever ways neccessary
   Ok(server)
}

fn setup_routes_v1(mut server: Route<'_, Arc<AppState>>) {
    server
        .at("hello-world")
        .get(|req: AppRequest| async move {
            Ok(req.state().greeting)
        });
}

fn setup_routes_v2(mut server: Route<'_, Arc<AppState>>) {
    server
        .at("hello-world")
        .get(|req: AppRequest| async move {
            Ok("Hello from v2!")
        });
}

preroll::main!(
    "hello-world",
    setup_app_state,
    setup_custom,
    (setup_routes_v1, setup_routes_v2)
);