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. Extractors are infallible, meaning they will always succeed and never return an error. In the case where a header is not present, the extractor will return None
or false
dependant on the expected return type.
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 redirect any requests without the header to "/" by default.
It should be noted that this is NOT a replacement for an auth guard. A user can trivially set the HX-Request
header themselves. This is merely a convenience for preventing users from receiving partial responses without context. If you need to secure an endpoint you should be using a proper auth system.
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 router_one() -> Router {
Router::new()
// Redirects to "/" if the HX-Request header is not present
.layer(HxRequestGuardLayer::default())
}
fn router_two() -> Router {
Router::new()
.layer(HxRequestGuardLayer::new("/redirect-to-this-route"))
}
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.