Skip to main content

Intro

What is Strut?

note

This documentation assumes basic understanding of the Rust programming language and Cargo, the Rust package manager. If you are completely new, follow the links to learn about these wonderful tools.

Strut refers to the strut crate. It’s main job is to simplify common backend chores:

What’s included by default

The strut crate has many features, but none of them are enabled by default. At the baseline, these well-known crates are always pulled in by Strut:

  • config: to load the application config from files & environment.
  • tokio: to build the asynchronous runtime for the application.
  • serde: to conveniently deserialize the external config.
  • dotenvy: to support environment defaults from .env files.
  • Implementation details, such as parking_lot.
Tokio?

Yes, Strut requires an asynchronous runtime, and makes an opinionated choice for Tokio. This comes from the fact that almost all Strut components have some sort of async play in them.

No, there is no option to switch to alternatives such as smol. Tokio is a robust, well-maintained, and widely adopted runtime. Additionally, the kind of applications that Strut aims at are not expected to bottleneck their performance on runtime choice.

Bare metal?

Strut is not designed for bare-metal applications, a.k.a. no-std, or embedded systems without an OS.

Instead, Strut targets the “classical” backend applications: web/API servers, macro-/microservices, data processors, etc., where the binary size is not expected to be a constraining factor.

Install Strut

Adding Strut to a binary crate is as simple as:

  1. Add Strut dependency with cargo add strut.
  2. Prefix the #[strut::main] attribute to the main function, and make it async.
src/main.rs
#[strut::main]
async fn main() {
// ...
}
Already using Tokio?

It’s ok to replace the #[tokio::main] attribute with #[strut::main]. The latter wraps and includes the former.

If the Tokio runtime needs to be customized, this is possible using a custom RuntimeWiring.

Launchpad

The #[strut::main] attribute is designed for simplistic use-cases. It is equivalent to:

fn main() {
let body = async {
// ...
};
strut::App::boot(body);
}

The call to the App::boot method is itself equivalent to:

fn main() {
let body = async {
// ...
};
strut::Launchpad::new(body).boot();
}

The Launchpad object exposes a number of pre-boot customizations. If you want to customize how Strut boots the application, Launchpad should be the first thing to look at.

Next steps

The base Strut dependency spins up a Tokio runtime and loads the application configuration. Without any components, the configuration is practically empty. Adding a component, such as tracing is the logical next step.

For crates and use-cases not yet baked into Strut, custom integrations are possible.