Expand description
axum-htmx
axum-htmx
is a small extension library providing extractors, responders, and
request guards for htmx headers within
axum.
Table of Contents
Getting Started
Run cargo add axum-htmx
to add the library to your project.
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<axum::http::Uri> |
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> |
Responders
All of the htmx response headers
have a supported responder. A responder is a basic type that implements
IntoResponseParts
, allowing you to simply and safely apply the HX-* headers to
any of your responses.
Header | Responder | Value |
---|---|---|
HX-Location | HxLocation | axum::http::Uri |
HX-Push-Url | HxPushUrl | axum::http::Uri |
HX-Redirect | HxRedirect | axum::http::Uri |
HX-Refresh | HxRefresh | bool |
HX-Replace-Url | HxReplaceUrl | axum::http::Uri |
HX-Reswap | HxReswap | axum_htmx::responders::SwapOption |
HX-Retarget | HxRetarget | String |
HX-Reselect | HxReselect | String |
HX-Trigger | HxResponseTrigger | axum_htmx::serde::HxEvent |
HX-Trigger-After-Settle | HxResponseTrigger | axum_htmx::serde::HxEvent |
HX-Trigger-After-Swap | HxResponseTrigger | axum_htmx::serde::HxEvent |
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.
Examples
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: Responders
We can trigger any event being listened to by the DOM using an htmx trigger header.
use axum_htmx::HxResponseTrigger;
// When we load our page, we will trigger any event listeners for "my-event.
async fn index() -> (&'static str, HxResponseTrigger) {
(
"Hello, world!",
HxResponseTrigger::normal(["my-event", "second-event"]),
)
}
htmx
also allows arbitrary data to be sent along with the event, which we can
use via the serde
feature flag and the HxEvent
type.
use serde_json::json;
// Note that we are using `HxResponseTrigger` from the `axum_htmx::serde` module
// instead of the root module.
use axum_htmx::{HxEvent, HxResponseTrigger};
async fn index() -> (&'static str, HxResponseTrigger) {
let event = HxEvent::new_with_data(
"my-event",
// May be any object that implements `serde::Serialize`
json!({"level": "info", "message": {
"title": "Hello, world!",
"body": "This is a test message.",
}}),
)
.unwrap();
("Hello, world!", HxResponseTrigger::normal([event]))
}
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 |
serde | Disabled | Adds serde support for the HxEvent and LocationOptions | serde , serde_json |
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.
Modules
- Axum extractors for htmx request headers.
- guard
guards
Request guard for protecting a router against non-htmx requests. - HTTP headers used by htmx.
- Axum responses for htmx response headers.
Structs
- The
HX-Boosted
header. - The
HX-Current-Url
header. - Represents a client-side event carrying optional data.
- The
HX-History-Restore-Request
header. - The
HX-Location
header. - The
HX-Prompt
header. - The
HX-Push-Url
header. - The
HX-Redirect
header. - The
HX-Refresh
header. - The
HX-Replace-Url
header. - The
HX-Request
header. - HxRequestGuard
guards
Tower service that implementes redirecting to non-partial routes. - HxRequestGuardLayer
guards
Checks if the request contains theHX-Request
header, redirecting to the given location if not. - The
HX-Reselect
header. - The
HX-Trigger*
header. - The
HX-Reswap
header. - The
HX-Retarget
header. - The
HX-Target
header. - The
HX-Trigger
header. - The
HX-Trigger-Name
header. - LocationOptions
serde
More options forHX-Location
header.
Enums
- Values of the
hx-swap
attribute. - Describes when should event be triggered.
Constants
- Indicates that the request is via an element using
hx-boost
attribute. - The current URL of the browser.
true
if the request is for history restoration after a miss in the local history cache.- Allows you to do a client-side redirect that does not do a full page reload.
- The user response to an
hx-prompt
- Pushes a new URL onto the history stack.
- Can be used to do a client-side redirect to a new location.
- If set to
true
, the client will do a full refresh on the page. - Replaces the currelt URL in the location bar.
- Always
true
. - A CSS selector that allows you to choose which part of the response is used to be swapped in. Overrides an existing
hx-select
on the triggering element - Allows you to specify how the response value will be swapped.
- A CSS selector that update the target of the content update to a different element on the page.
- The
id
of the target element, if it exists. - Can be set as a request or response header.
- Allows you to trigger client-side events.
- Allows you to trigger client-side events.
- The
name
of the triggered element, if it exists.