From 4eae8b3fe2d1160feb3ea889fcacbd428cb45acb Mon Sep 17 00:00:00 2001 From: Dmitry Kudryavtsev Date: Tue, 3 Jun 2025 20:49:41 +0200 Subject: [PATCH] Remove `Uri` from responders - replace with `String` (#32) * remove `Uri` from responders - replace with `String` * clean clippy warnings --- README.md | 8 ++-- src/responders.rs | 58 +++++++++-------------------- src/responders/location.rs | 75 +++++++++----------------------------- 3 files changed, 39 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index ab39236..fdd0726 100644 --- a/README.md +++ b/README.md @@ -65,11 +65,11 @@ 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-Location` | `HxLocation` | `String` | +| `HX-Push-Url` | `HxPushUrl` | `String` | +| `HX-Redirect` | `HxRedirect` | `String` | | `HX-Refresh` | `HxRefresh` | `bool` | -| `HX-Replace-Url` | `HxReplaceUrl` | `axum::http::Uri` | +| `HX-Replace-Url` | `HxReplaceUrl` | `String` | | `HX-Reswap` | `HxReswap` | `axum_htmx::responders::SwapOption` | | `HX-Retarget` | `HxRetarget` | `String` | | `HX-Reselect` | `HxReselect` | `String` | diff --git a/src/responders.rs b/src/responders.rs index e7de8d2..69e0abe 100644 --- a/src/responders.rs +++ b/src/responders.rs @@ -1,9 +1,9 @@ //! Axum responses for htmx response headers. -use std::{convert::Infallible, str::FromStr}; +use std::convert::Infallible; use axum_core::response::{IntoResponseParts, ResponseParts}; -use http::{HeaderValue, Uri}; +use http::HeaderValue; use crate::{headers, HxError}; @@ -32,7 +32,7 @@ const HX_SWAP_NONE: &str = "none"; /// /// See for more information. #[derive(Debug, Clone)] -pub struct HxPushUrl(pub Uri); +pub struct HxPushUrl(pub String); impl IntoResponseParts for HxPushUrl { type Error = HxError; @@ -40,24 +40,16 @@ impl IntoResponseParts for HxPushUrl { fn into_response_parts(self, mut res: ResponseParts) -> Result { res.headers_mut().insert( headers::HX_PUSH_URL, - HeaderValue::from_maybe_shared(self.0.to_string())?, + HeaderValue::from_maybe_shared(self.0)?, ); Ok(res) } } -impl From for HxPushUrl { - fn from(uri: Uri) -> Self { - Self(uri) - } -} - -impl<'a> TryFrom<&'a str> for HxPushUrl { - type Error = ::Err; - - fn try_from(value: &'a str) -> Result { - Ok(Self(value.parse()?)) +impl<'a> From<&'a str> for HxPushUrl { + fn from(value: &'a str) -> Self { + Self(value.to_string()) } } @@ -68,7 +60,7 @@ impl<'a> TryFrom<&'a str> for HxPushUrl { /// Will fail if the supplied Uri contains characters that are not visible ASCII /// (32-127). #[derive(Debug, Clone)] -pub struct HxRedirect(pub Uri); +pub struct HxRedirect(pub String); impl IntoResponseParts for HxRedirect { type Error = HxError; @@ -76,24 +68,16 @@ impl IntoResponseParts for HxRedirect { fn into_response_parts(self, mut res: ResponseParts) -> Result { res.headers_mut().insert( headers::HX_REDIRECT, - HeaderValue::from_maybe_shared(self.0.to_string())?, + HeaderValue::from_maybe_shared(self.0)?, ); Ok(res) } } -impl From for HxRedirect { - fn from(uri: Uri) -> Self { - Self(uri) - } -} - -impl<'a> TryFrom<&'a str> for HxRedirect { - type Error = ::Err; - - fn try_from(value: &'a str) -> Result { - Ok(Self(value.parse()?)) +impl<'a> From<&'a str> for HxRedirect { + fn from(value: &'a str) -> Self { + Self(value.to_string()) } } @@ -137,7 +121,7 @@ impl IntoResponseParts for HxRefresh { /// /// See for more information. #[derive(Debug, Clone)] -pub struct HxReplaceUrl(pub Uri); +pub struct HxReplaceUrl(pub String); impl IntoResponseParts for HxReplaceUrl { type Error = HxError; @@ -145,24 +129,16 @@ impl IntoResponseParts for HxReplaceUrl { fn into_response_parts(self, mut res: ResponseParts) -> Result { res.headers_mut().insert( headers::HX_REPLACE_URL, - HeaderValue::from_maybe_shared(self.0.to_string())?, + HeaderValue::from_maybe_shared(self.0)?, ); Ok(res) } } -impl From for HxReplaceUrl { - fn from(uri: Uri) -> Self { - Self(uri) - } -} - -impl<'a> TryFrom<&'a str> for HxReplaceUrl { - type Error = ::Err; - - fn try_from(value: &'a str) -> Result { - Ok(Self(value.parse()?)) +impl<'a> From<&'a str> for HxReplaceUrl { + fn from(value: &'a str) -> Self { + Self(value.to_string()) } } diff --git a/src/responders/location.rs b/src/responders/location.rs index 92c2a82..744a613 100644 --- a/src/responders/location.rs +++ b/src/responders/location.rs @@ -1,7 +1,5 @@ -use std::str::FromStr; - use axum_core::response::{IntoResponseParts, ResponseParts}; -use http::{HeaderValue, Uri}; +use http::HeaderValue; use crate::{headers, HxError}; @@ -12,14 +10,14 @@ use crate::{headers, HxError}; /// target on the page, you must enable the `serde` feature flag and specify /// [`LocationOptions`]. /// -/// Will fail if the supplied Uri contains characters that are not visible ASCII +/// Will fail if the supplied uri contains characters that are not visible ASCII /// (32-127). /// /// See for more information. #[derive(Debug, Clone)] pub struct HxLocation { /// Uri of the new location. - pub uri: Uri, + pub uri: String, /// Extra options. #[cfg(feature = "serde")] #[cfg_attr(feature = "unstable", doc(cfg(feature = "serde")))] @@ -27,43 +25,24 @@ pub struct HxLocation { } impl HxLocation { - /// Creates location from [`Uri`] without any options. - pub fn from_uri(uri: Uri) -> Self { + /// Parses `uri` and sets it as location. + #[allow(clippy::should_implement_trait)] + pub fn from_str(uri: impl AsRef) -> Self { Self { #[cfg(feature = "serde")] options: LocationOptions::default(), - uri, + uri: uri.as_ref().to_string(), } } - /// Creates location from [`Uri`] and options. - #[cfg(feature = "serde")] - #[cfg_attr(feature = "unstable", doc(cfg(feature = "serde")))] - pub fn from_uri_with_options(uri: Uri, options: LocationOptions) -> Self { - Self { uri, options } - } - - /// Parses `uri` and sets it as location. - #[allow(clippy::should_implement_trait)] - pub fn from_str(uri: impl AsRef) -> Result { - Ok(Self { - #[cfg(feature = "serde")] - options: LocationOptions::default(), - uri: uri.as_ref().parse::()?, - }) - } - /// Parses `uri` and sets it as location with additional options. #[cfg(feature = "serde")] #[cfg_attr(feature = "unstable", doc(cfg(feature = "serde")))] - pub fn from_str_with_options( - uri: impl AsRef, - options: LocationOptions, - ) -> Result { - Ok(Self { + pub fn from_str_with_options(uri: impl AsRef, options: LocationOptions) -> Self { + Self { options, - uri: uri.as_ref().parse::()?, - }) + uri: uri.as_ref().to_string(), + } } #[cfg(feature = "serde")] @@ -88,34 +67,16 @@ impl HxLocation { } } -impl From for HxLocation { - fn from(uri: Uri) -> Self { - Self::from_uri(uri) - } -} - -#[cfg(feature = "serde")] -#[cfg_attr(feature = "unstable", doc(cfg(feature = "serde")))] -impl From<(Uri, LocationOptions)> for HxLocation { - fn from((uri, options): (Uri, LocationOptions)) -> Self { - Self::from_uri_with_options(uri, options) - } -} - -impl<'a> TryFrom<&'a str> for HxLocation { - type Error = ::Err; - - fn try_from(uri: &'a str) -> Result { +impl<'a> From<&'a str> for HxLocation { + fn from(uri: &'a str) -> Self { Self::from_str(uri) } } #[cfg(feature = "serde")] #[cfg_attr(feature = "unstable", doc(cfg(feature = "serde")))] -impl<'a> TryFrom<(&'a str, LocationOptions)> for HxLocation { - type Error = ::Err; - - fn try_from((uri, options): (&'a str, LocationOptions)) -> Result { +impl<'a> From<(&'a str, LocationOptions)> for HxLocation { + fn from((uri, options): (&'a str, LocationOptions)) -> Self { Self::from_str_with_options(uri, options) } } @@ -207,11 +168,11 @@ mod tests { fn test_serialize_location() { use crate::SwapOption; - let loc = HxLocation::try_from("/foo").unwrap(); + let loc = HxLocation::from("/foo"); assert_eq!(loc.into_header_with_options().unwrap(), "/foo"); - let loc = HxLocation::from_uri_with_options( - "/foo".parse().unwrap(), + let loc = HxLocation::from_str_with_options( + "/foo", LocationOptions { event: Some("click".into()), swap: Some(SwapOption::InnerHtml),