rama_http/service/web/endpoint/extract/
path.rs1use super::FromPartsStateRefPair;
4use crate::matcher::{UriParams, UriParamsDeserializeError};
5use crate::request::Parts;
6use crate::utils::macros::{composite_http_rejection, define_http_rejection};
7use serde::de::DeserializeOwned;
8use std::ops::{Deref, DerefMut};
9
10#[derive(Debug, Clone)]
12pub struct Path<T>(pub T);
13
14define_http_rejection! {
15 #[status = INTERNAL_SERVER_ERROR]
16 #[body = "No paths parameters found for matched route"]
17 pub struct MissingPathParams;
19}
20
21composite_http_rejection! {
22 pub enum PathRejection {
27 UriParamsDeserializeError,
28 MissingPathParams,
29 }
30}
31
32impl<T, State> FromPartsStateRefPair<State> for Path<T>
33where
34 T: DeserializeOwned + Send + Sync + 'static,
35 State: Send + Sync,
36{
37 type Rejection = PathRejection;
38
39 async fn from_parts_state_ref_pair(
40 parts: &Parts,
41 _state: &State,
42 ) -> Result<Self, Self::Rejection> {
43 match parts.extensions.get_ref::<UriParams>() {
44 Some(params) => {
45 let params = params.deserialize::<T>()?;
46 Ok(Self(params))
47 }
48 None => Err(MissingPathParams.into()),
49 }
50 }
51}
52
53impl<T> Deref for Path<T> {
54 type Target = T;
55
56 fn deref(&self) -> &Self::Target {
57 &self.0
58 }
59}
60
61impl<T> DerefMut for Path<T> {
62 fn deref_mut(&mut self) -> &mut Self::Target {
63 &mut self.0
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 use crate::service::web::WebService;
72 use crate::{Body, Request, StatusCode};
73 use rama_core::Service;
74
75 #[tokio::test]
76 async fn test_host_from_request() {
77 #[derive(Debug, serde::Deserialize)]
78 struct Params {
79 foo: String,
80 bar: u32,
81 }
82
83 let svc = WebService::default().with_get(
84 "/a/{foo}/{bar}/b/{}",
85 async |Path(params): Path<Params>| {
86 assert_eq!(params.foo, "hello");
87 assert_eq!(params.bar, 42);
88 StatusCode::OK
89 },
90 );
91
92 let builder = Request::builder()
93 .method("GET")
94 .uri("http://example.com/a/hello/42/b/extra");
95 let req = builder.body(Body::empty()).unwrap();
96
97 let resp = svc.serve(req).await.unwrap();
98 assert_eq!(resp.status(), StatusCode::OK);
99 }
100}