laxum 0.2.2

Make working with Axum a little smoother.
Documentation
# 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);
```