# Make Axum a little smoother
(c) [d2718](https://codeberg.org/d2718);
[MIT license](https://opensource.org/license/mit)
## Motivation
I use Axum a great deal, both in my personal projects and at work. I have,
as one does when one uses anything with frequency, identified a
miscellaney of snags and irritations; this crate is an attempt to smooth
and soothe those.
This is in no way meant to be a complaint about axum or a criticism of
any of the Tokio team's grave contributions to the Rust ecosystem; this is
simply an adapter for _my_ habitual use cases which I have chosen to
publish in case some part of it might also be of use to others.
## Features
### Ergonomic Early-Return Error Handling
The [`LaxErr`] provides a flexible error type which implements
[`IntoResponse`](axum::response::IntoResponse);
a companion [`Laxative<T>`] trait enables returning error responses
ergonomically from `Result<T, LaxErr>` with more control than a simple '?'
provides.
```rust ignore
use eyre::{OptionExt, WrapErr};
use http::status::StatusCode;
use laxum::{GetStrHeaders, Laxative};
let auth_key = request.get_str("authorizaiton")
.ok_or_eyre("request requires Authorization: header")
.with_status(StatusCode::BAD_REQUEST)?;
```
### Ergonomic Header Extraction
```rust ignore
use axum::response::{IntoResponse, Response};
use laxum::{GetHeaders LaxErr, Laxative};
async fn handler(req: Request) -> Result<Response, LaxErr> {
let action = request.require_str("x-action")?;
// do something with `action` here...
}
```
If the request lacks a comprehensible `x-action` header, they'll get a
400 response with the message "Request requires 'x-action' header."
### A Layer to add Multiple Headers
`tower-http` has
[`SetResponseHeaderLayer`](https://docs.rs/tower-http/latest/tower_http/set_header/struct.SetResponseHeaderLayer.html),
but that will only add one header per layer; the
[`laxum::AddHeadersLayer`](AddHeadersLayer) can add an arbitrary number
of them.
```rust ignore
use axum::routing::Router;
use http::header::{self, HeaderValue};
use laxum::AddHeadersLayer;
let add_headers = AddHeadersLayer::build()
.with(header::SERVER, HeaderValue::from_static("something-cool v0.2.14"))
.with("x-clacks-overhead", HeaderValue::from_static("GNU Terry Pratchett, Jordan Dudash"))
.to_layer();
let router = Router::new()
// A bunch of routes go here...
.layer(add_headers);
```