diff --git a/axum-extra/CHANGELOG.md b/axum-extra/CHANGELOG.md index 00764fd4..1319fec8 100644 --- a/axum-extra/CHANGELOG.md +++ b/axum-extra/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning]. # Unreleased +- **added:** Add `TypedPath::to_uri` for converting the path into a `Uri` ([#790]) - **added:** Add type safe routing. See `axum_extra::routing::typed` for more details ([#756]) - **breaking:** `CachedRejection` has been removed ([#699]) - **breaking:** ` as FromRequest>::Rejection` is now `T::Rejection`. ([#699]) @@ -16,6 +17,7 @@ and this project adheres to [Semantic Versioning]. [#699]: https://github.com/tokio-rs/axum/pull/699 [#719]: https://github.com/tokio-rs/axum/pull/719 [#756]: https://github.com/tokio-rs/axum/pull/756 +[#790]: https://github.com/tokio-rs/axum/pull/790 # 0.1.2 (13. January, 2022) diff --git a/axum-extra/src/routing/typed.rs b/axum-extra/src/routing/typed.rs index 5c855453..89294daf 100644 --- a/axum-extra/src/routing/typed.rs +++ b/axum-extra/src/routing/typed.rs @@ -1,4 +1,5 @@ use super::sealed::Sealed; +use http::Uri; /// A type safe path. /// @@ -87,6 +88,8 @@ use super::sealed::Sealed; /// things, create links to known paths and have them verified statically. Note that the /// [`Display`] implementation for each field must return something that's compatible with its /// [`Deserialize`] implementation. +/// - A [`TryFrom<_> for Uri`](std::convert::TryFrom) implementation to converting your paths into +/// [`Uri`](axum::http::Uri). /// /// Additionally the macro will verify the captures in the path matches the fields of the struct. /// For example this fails to compile since the struct doesn't have a `team_id` field: @@ -148,6 +151,21 @@ use super::sealed::Sealed; pub trait TypedPath: std::fmt::Display { /// The path with optional captures such as `/users/:id`. const PATH: &'static str; + + /// Convert the path into a `Uri`. + /// + /// # Panics + /// + /// The default implementation parses the required [`Display`] implemetation. If that fails it + /// will panic. + /// + /// Using `#[derive(TypedPath)]` will never result in a panic since it percent-encodes + /// arguments. + /// + /// [`Display`]: std::fmt::Display + fn to_uri(&self) -> Uri { + self.to_string().parse().unwrap() + } } /// Utility trait used with [`RouterExt`] to ensure the first element of a tuple type is a diff --git a/axum-macros/CHANGELOG.md b/axum-macros/CHANGELOG.md index da3338d0..3346a5ea 100644 --- a/axum-macros/CHANGELOG.md +++ b/axum-macros/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # Unreleased -- Add `#[derive(TypedPath)]` for use with axum-extra's new "type safe" routing API ([#756]) +- **added:** Add `#[derive(TypedPath)]` for use with axum-extra's new "type safe" routing API ([#756]) # 0.1.0 (31. January, 2022) diff --git a/axum-macros/src/typed_path.rs b/axum-macros/src/typed_path.rs index bb3fd48d..3336584f 100644 --- a/axum-macros/src/typed_path.rs +++ b/axum-macros/src/typed_path.rs @@ -29,7 +29,7 @@ pub(crate) fn expand(item_struct: ItemStruct) -> syn::Result { let segments = parse_path(&path)?; expand_unnamed_fields(fields, ident, path, &segments) } - syn::Fields::Unit => Ok(expand_unit_fields(ident, path)?), + syn::Fields::Unit => expand_unit_fields(ident, path), } } diff --git a/axum-macros/tests/typed_path/pass/into_uri.rs b/axum-macros/tests/typed_path/pass/into_uri.rs new file mode 100644 index 00000000..5276627c --- /dev/null +++ b/axum-macros/tests/typed_path/pass/into_uri.rs @@ -0,0 +1,23 @@ +use axum_extra::routing::TypedPath; +use axum::http::Uri; +use serde::Deserialize; + +#[derive(TypedPath, Deserialize)] +#[typed_path("/:id")] +struct Named { + id: u32, +} + +#[derive(TypedPath, Deserialize)] +#[typed_path("/:id")] +struct Unnamed(u32); + +#[derive(TypedPath, Deserialize)] +#[typed_path("/")] +struct Unit; + +fn main() { + let _: Uri = Named { id: 1 }.to_uri(); + let _: Uri = Unnamed(1).to_uri(); + let _: Uri = Unit.to_uri(); +}