1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
use axum::{
async_trait,
extract::{rejection::MatchedPathRejection, FromRequestParts, MatchedPath},
http::request::Parts,
RequestPartsExt,
};
/// Extracts matched path of the request
///
/// # Usage
///
/// ```
/// # use axum::{response::IntoResponse, Server, Router, routing::get};
/// # use axum_template::Key;
/// async fn handler(
/// Key(key): Key
/// ) -> impl IntoResponse
/// {
/// key
/// }
///
/// let router = Router::new()
/// // key == "/some/route"
/// .route("/some/route", get(handler))
/// // key == "/:dynamic"
/// .route("/:dynamic", get(handler));
///
/// # async {
/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
/// .serve(router.into_make_service())
/// .await
/// .expect("server failed");
/// # };
/// ```
///
/// # Additional resources
///
/// - [`MatchedPath`]
/// - Example: [`custom_key.rs`]
///
/// [`MatchedPath`]: axum::extract::MatchedPath
/// [`custom_key.rs`]: https://github.com/Altair-Bueno/axum-template/blob/main/examples/custom_key.rs
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Key(pub String);
#[async_trait]
impl<S> FromRequestParts<S> for Key
where
S: Send + Sync,
{
type Rejection = MatchedPathRejection;
async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
let path = parts.extract::<MatchedPath>().await?.as_str().to_owned();
Ok(Key(path))
}
}
impl AsRef<str> for Key {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl From<String> for Key {
fn from(s: String) -> Self {
Self(s)
}
}