The routes! DSL Reference
Resources, methods, and formats are just normal Rust code, but they are brought
together in the routes!
macro, which implements a complicated domain specific
language for assembling your application in a declarative way.
Just implementing a method for a resource isn't enough to create an endpoint;
it also needs to be added to your routes!
macro, which looks like this:
# #![allow(unused_variables)] #fn main() { use cargonauts::methods::Get; use cargonauts::formats::JsonApi; use resources::User; routes! { resource User { method Get in JsonApi; } } #}
Having implemented Get for User (as well as the traits required to format a
User with JsonApi), this will create an endpoint for GET /user/$id
. If you
haven't implemented all of the necessary traits, you will get a compiler error.
Every CamelCase name in the routes!
macro is just a type imported into this
scope; there's no magic lookup for User, Get, or JsonApi, you have to have
imported them into this module in order to use them in the DSL.
The rest of this page will document the syntax for the routes!
DSL.
Resource blocks
A resource block looks like this:
resource $TYPE {
...
}
The $TYPE must implement the Resource trait.
By default, resources will be mounted at the kebab case form of the type
name - that is, all lowercase, joined by hyphens. For example, User
will
be mounted at user
, whereas a resource called HappyDoggo
would be mounted
at happy-doggo
.
If you don't like that route choice, you can use an as
clause to rename it.
This takes a string literal. For example, you might prefer plural route names;
cargonauts will not automatically inflect your names for you, you'll have to
specify them:
resource Person as "people" {
...
}
resource Cat as "cats" {
}
resource Doggo as "puppers" {
}
Method statements
Within a resource block, you can declare the methods that resource supports. A method takes the syntax:
method $METHOD in $FORMAT;
Where $METHOD is a method trait, and $FORMAT is a type which implements Format.
You can have multiple methods using the same format on the same line, separated with commas, or not:
method Get, Index, Post in JsonApi;
method Patch in Handlebars;
method Delete in Handlebars;
Currently each method can only be provided in one format, someday this will change to support dispatching to different formats based on the Accepts headers.
Relationship blocks
Resources can also contain relationships, which can be either has one
or
has many
:
resource BlogPost {
has one Author {
...
}
has many Comment {
...
}
}
The type of a relationship block must implement Relationship. Like resource
blocks, these support aliases with as
, and they can contain method
statements. Their method statements must be relationship methods:
resource BlogPost {
has many Comment as "comments" {
method GetMany in JsonApi;
}
}
Modules
Resources can be put into inline modules; modules use the same syntax as in regular Rust, and can be nested:
mod api {
mod foo_bar {
resource Baz {
...
}
}
}
These will create directories in the API; for example, Baz's endpoints would
be mounted at api/foo-bar/baz
. Note that modules, like types, are kebab
cased in the actual API.
These are only used to control the shape of the API; there is no namespacing
or use statements inside the routes!
DSL.
Setup block
The routes!
DSL can also begin with a setup
block. This block is used to
set up connections to other services when the application starts.
The setup block looks like this:
setup {
connection to $SERVICE;
}
$SERVICE must be a type which implements NewService and Configure. Connections to this service will be managed by a connection pool which you can configure with your Cargo.toml.
Asset handler
By default, assets will be presented with a very simple asset handler, providing few headers or other processing. If you wish to perform more complex handling for your assets, you can define an asset hnadler function. This function must have the signature:
fn(path: &'static Path, asset: &'static [u8], req: middleware::Request) -> middleware::http::BoxFuture
You can tell cargonauts to use this handler instead of the default with this
statement at the beginning of the routes!
DSL:
use $ASSET_HANDLER for assets;