No description
Find a file
2023-07-27 22:21:05 -04:00
src Add router request guard layer 2023-07-27 21:58:53 -04:00
.gitignore Initial commit 2023-07-22 16:37:15 -04:00
Cargo.toml Update meta information 2023-07-27 22:21:05 -04:00
LICENSE-APACHE Fix Apache license to show up on new GitHub repo pages 2023-07-27 19:05:57 -04:00
LICENSE-MIT Clean up license files to display properly on GitHub 2023-07-27 19:03:22 -04:00
README.md Update README.md 2023-07-27 22:02:16 -04:00
rustfmt.toml Initial commit 2023-07-22 16:37:15 -04:00

axum-htmx


axum-htmx is a small extension library providing extractors and request guards for the various htmx headers within axum. Additionally, the library exports const values for all of the htmx headers, so there's no need to mess with strings in your handlers.

Getting Started

Simply run cargo add axum-htmx to add the library to your project.

If you are using the unreleased branch of axum from GitHub, you can build against the main version of axum-htmx by adding the following to your Cargo.toml:

[dependencies]
axum-htmx = { git = "https://github.com/robertwayne/axum-htmx" }

Extractors

All of the htmx request headers have a supported extractor. Additionally, all extractors are infallible, meaning they will always succeed and never return an error. If the header is not present, the extractor will return None or false in most cases.

Header Extractor Value
HX-Boosted HxBoosted bool
HX-Current-URL HxCurrentUrl Option<String>
HX-History-Restore-Request HxHistoryRestoreRequest bool
HX-Prompt HxPrompt Option<String>
HX-Request HxRequest bool
HX-Target HxTarget Option<String>
HX-Trigger-Name HxTriggerName Option<String>
HX-Trigger HxTrigger Option<String>

Request Guards

Requires features guards.

In addition to the extractors, there is also a route-wide layer request guard for the HX-Request header. This will return a 403: Forbidden response if the header is not present, which is useful if you want to make an entire router, say /api, only accessible via htmx requests.

Example: Extractors

In this example, we'll look for the HX-Boosted header, which is set when applying the hx-boost attribute to an element. In our case, we'll use it to determine what kind of response we send.

When is this useful? When using a templating engine, like minijinja, it is common to extend different templates from a _base.html template. However, htmx works by sending partial responses, so extending our _base.html would result in lots of extra data being sent over the wire.

If we wanted to swap between pages, we would need to support both full template responses and partial responses (as the page can be accessed directly or through a boosted anchor), so we look for the HX-Boosted header and extend from a _partial.html template instead.

use axum::response::IntoResponse;
use axum_htmx::HxBoosted;

async fn get_index(HxBoosted(boosted): HxBoosted) -> impl IntoResponse {
    if boosted {
        // Send a template extending from _partial.html
    } else {
        // Send a template extending from _base.html
    }
}

Example: Router Guard

use axum::Router;
use axum_htmx::HxRequestGuardLayer;

fn protected_router() -> Router {
    Router::new()
        .layer(HxRequestGuardLayer::new())
}

Feature Flags

Flag Default Description Dependencies
guards Disabled Adds request guard layers. tower, futures-core, pin-project-lite

Contributing

Contributions are always welcome! If you have an idea for a feature or find a bug, let me know. PR's are appreciated, but if it's not a small change, please open an issue first so we're all on the same page!

License

axum-htmx is dual-licensed under either

at your option.