mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-28 00:00:20 +02:00
Backport TypedPath::to_uri (#809)
* axum-macros: use fully qualified Result type (#796) * Easily convert typed paths into URIs (#790) * Easily convert typed paths into URIs `#[derive(TypedPath)]` will now also generate `TryFrom<_> for Uri` for easily converting paths into URIs for use with `Redirect` and friends. Fixes https://github.com/tokio-rs/axum/issues/789 * Use a method on the `TypedPath` trait to convert to `Uri` * fix doc ref * Update changelogs * Remove out of date docs These accidentally weren't removed in https://github.com/tokio-rs/axum/pull/790 Co-authored-by: Matthias Vogelgesang <[email protected]>
This commit is contained in:
co-authored by
Matthias Vogelgesang
parent
558a4d05b0
commit
84cbb66575
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
# Unreleased
|
||||
|
||||
- None.
|
||||
- **added:** Add `TypedPath::to_uri` for converting the path into a `Uri` ([#790])
|
||||
|
||||
[#790]: https://github.com/tokio-rs/axum/pull/790
|
||||
|
||||
# 0.1.4 (22. February, 2022)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::sealed::Sealed;
|
||||
use http::Uri;
|
||||
|
||||
/// A type safe path.
|
||||
///
|
||||
@@ -148,6 +149,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
|
||||
|
||||
@@ -29,7 +29,7 @@ pub(crate) fn expand(item_struct: ItemStruct) -> syn::Result<TokenStream> {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ fn expand_named_fields(ident: &syn::Ident, path: LitStr, segments: &[Segment]) -
|
||||
{
|
||||
type Rejection = <::axum::extract::Path<Self> as ::axum::extract::FromRequest<B>>::Rejection;
|
||||
|
||||
async fn from_request(req: &mut ::axum::extract::RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
async fn from_request(req: &mut ::axum::extract::RequestParts<B>) -> ::std::result::Result<Self, Self::Rejection> {
|
||||
::axum::extract::Path::from_request(req).await.map(|path| path.0)
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ fn expand_unnamed_fields(
|
||||
{
|
||||
type Rejection = <::axum::extract::Path<Self> as ::axum::extract::FromRequest<B>>::Rejection;
|
||||
|
||||
async fn from_request(req: &mut ::axum::extract::RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
async fn from_request(req: &mut ::axum::extract::RequestParts<B>) -> ::std::result::Result<Self, Self::Rejection> {
|
||||
::axum::extract::Path::from_request(req).await.map(|path| path.0)
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ fn expand_unit_fields(ident: &syn::Ident, path: LitStr) -> syn::Result<TokenStre
|
||||
{
|
||||
type Rejection = ::axum::http::StatusCode;
|
||||
|
||||
async fn from_request(req: &mut ::axum::extract::RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
async fn from_request(req: &mut ::axum::extract::RequestParts<B>) -> ::std::result::Result<Self, Self::Rejection> {
|
||||
if req.uri().path() == <Self as ::axum_extra::routing::TypedPath>::PATH {
|
||||
Ok(Self)
|
||||
} else {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
use axum_extra::routing::TypedPath;
|
||||
use serde::Deserialize;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, ()>;
|
||||
|
||||
#[derive(TypedPath, Deserialize)]
|
||||
#[typed_path("/users/:user_id/teams/:team_id")]
|
||||
struct MyPath(u32, u32);
|
||||
|
||||
Reference in New Issue
Block a user