htmxtools 0.1.1

A lightweight Rust crate for working with HTMX headers, specifically designed to integrate seamlessly with axum.
# htmxtools

A lightweight Rust crate for working with HTMX headers, specifically designed to integrate seamlessly with `axum`.

HTMX is a library that enhances HTML with AJAX capabilities, and it relies heavily on custom headers to enable
dynamic interactions. The `htmxtools` crate simplifies handling these headers in Rust, enabling you to easily
extract, process, and respond with HTMX-related data.

## Features

- **Request Extractors**: Easily extract HTMX headers from incoming requests.
- **Response Builders**: Conveniently build responses with HTMX headers.
- **Axum Integration**: Built on top of `typed-headers` in `axum-extra` for seamless integration with the `axum`.
- **Auto Vary**: Correctly handle response caching by automatically add the `Vary` header to responses based on the
  extracted HTMX headers.

## Usage

To use `htmxtools`, run the following command in your project directory:

```bash
cargo add htmxtools
```

If you don't want to use `axum`, you can still use the `htmxtools` crate with other web frameworks. The crate
implements `headers::Header` trait for all HTMX headers, so you can easily extract and build headers in any
framework that supports `headers::Header`.

To use `htmxtools` without `axum`, run the following command in your project directory:

```bash
cargo add htmxtools --no-default-features
```

### Request Extractors

To extract HTMX headers from incoming requests in `axum`, you can directly use headers in `htmxtools::request` in your
handler functions as they implement `FromRequestParts` and `OptionalFromRequestParts` traits.

Here's an example of extracting the `hx-request` header:

```rust
use axum_core::response::IntoResponse;
use htmxtools::request::HxRequest;

async fn handler(hx_request: Option<HxRequest>) -> impl IntoResponse {
    if hx_request.is_some() {
        "This is an HTMX request"
    } else {
        "This is not an HTMX request"
    }
}
```

Here's another example of extracting the `hx-target` header:

```rust
use axum_core::response::IntoResponse;
use htmxtools::request::HxTarget;

async fn handler(hx_target: HxTarget) -> impl IntoResponse {
    format!("The target is: {}", hx_target.as_str())
}

async fn another_handler(hx_target: Option<HxTarget>) -> impl IntoResponse {
    match hx_target {
        Some(target) => format!("The target is: {}", target.as_str()),
        None => "No target specified".to_string(),
    }
}
```

### Response Builders

To build responses with HTMX headers in `axum`, you can use headers in `htmxtools::response` in your handler functions
as they implement `IntoResponseParts` and `IntoResponse` traits.

Here's an example of building a response with the `hx-push-url` header:

```rust
use axum_core::response::IntoResponse;
use htmxtools::response::HxPushUrl;
use http::Uri;

async fn handler() -> impl IntoResponse {
    HxPushUrl::url(Uri::from_static("/new-url"))
}
```

Here's another example of building a response with `hx-retarget` and `hx-reswap` header:

```rust
use axum_core::response::IntoResponse;
use htmxtools::response::{HxReswap, HxRetarget};

async fn handler() -> impl IntoResponse {
    (HxReswap::inner_html(), HxRetarget::from_static("#body"), "<div></div>")
}
```

### Auto Vary

To automatically add the `Vary` header to responses based on the extracted HTMX headers in `axum`, you can use the
`AutoVaryLayer` in `htmxtools::auto_vary`.

To use the `AutoVaryLayer`, you need to enable the `auto-vary` feature in your `Cargo.toml`.

Here's an example of using the `AutoVaryLayer`:

```rust
use axum::Router;
use htmxtools::auto_vary::AutoVaryLayer;

fn app() -> Router {
    Router::new().layer(AutoVaryLayer)
}
```

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)
- MIT license ([LICENSE-MIT]LICENSE-MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as
defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.