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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
mod de;
use std::ops::{Deref, DerefMut};
use serde::de::DeserializeOwned;
use crate::{error::ErrorInvalidPathParams, FromRequest, Request, RequestBody, Result};
/// An extractor that will get captures from the URL and parse them using
/// `serde`.
///
/// # Example
///
/// ```
/// use poem::{handler, route, route::get, web::Path};
///
/// #[handler]
/// async fn users_teams_show(Path((user_id, team_id)): Path<(String, String)>) {
/// // ...
/// }
///
/// let mut app = route().at("/users/:user_id/team/:team_id", get(users_teams_show));
/// ```
///
/// If the path contains only one parameter, then you can omit the tuple.
///
/// ```
/// use poem::{handler, route, route::get, web::Path};
///
/// #[handler]
/// async fn user_info(Path(user_id): Path<String>) {
/// // ...
/// }
///
/// let mut app = route().at("/users/:user_id", get(user_info));
/// ```
///
/// Path segments also can be deserialized into any type that implements [`serde::Deserialize`](https://docs.rs/serde/1.0.127/serde/trait.Deserialize.html).
/// Path segment labels will be matched with struct field names.
///
/// ```
/// use poem::{handler, route, route::get, web::Path};
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
/// struct Params {
/// user_id: String,
/// team_id: String,
/// }
///
/// #[handler]
/// async fn users_teams_show(Path(Params { user_id, team_id }): Path<Params>) {
/// // ...
/// }
///
/// let mut app = route();
/// app.at("/users/:user_id/team/:team_id", get(users_teams_show));
/// ```
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Path<T>(pub T);
impl<T> Deref for Path<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Path<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[async_trait::async_trait]
impl<'a, T: DeserializeOwned> FromRequest<'a> for Path<T> {
type Error = ErrorInvalidPathParams;
async fn from_request(req: &'a Request, _body: &mut RequestBody) -> Result<Self, Self::Error> {
T::deserialize(de::PathDeserializer::new(&req.state().match_params))
.map_err(|_| ErrorInvalidPathParams)
.map(Path)
}
}