arcly_http_core/web/
extract.rs1use std::ops::Deref;
9use std::str::FromStr;
10use std::sync::Arc;
11
12use serde::de::DeserializeOwned;
13use validator::Validate;
14
15use crate::web::{Error, RequestContext};
16
17pub struct Inject<T: Send + Sync + 'static> {
26 inner: Arc<T>,
27}
28
29impl<T: Send + Sync + 'static> Inject<T> {
30 #[inline]
31 pub fn from_ctx(ctx: &RequestContext) -> Self {
32 Self {
33 inner: ctx.inject_arc::<T>(),
34 }
35 }
36 #[doc(hidden)]
39 #[inline]
40 pub fn __from_arc(inner: Arc<T>) -> Self {
41 Self { inner }
42 }
43 #[inline]
46 pub fn get(&self) -> &T {
47 &self.inner
48 }
49 #[inline]
51 pub fn arc(&self) -> Arc<T> {
52 Arc::clone(&self.inner)
53 }
54}
55
56impl<T: Send + Sync + 'static> Deref for Inject<T> {
57 type Target = T;
58 #[inline]
59 fn deref(&self) -> &T {
60 &self.inner
61 }
62}
63
64impl<T: Send + Sync + 'static> Clone for Inject<T> {
65 #[inline]
66 fn clone(&self) -> Self {
67 Self {
68 inner: Arc::clone(&self.inner),
69 }
70 }
71}
72
73#[inline]
79pub fn extract_param<T: FromStr>(ctx: &RequestContext, name: &'static str) -> Result<T, Error> {
80 let raw = ctx
81 .param(name)
82 .ok_or(Error::BadRequest("missing path parameter"))?;
83 raw.parse::<T>()
84 .map_err(|_| Error::BadRequest("invalid path parameter"))
85}
86
87#[inline]
88pub fn extract_query<T: DeserializeOwned>(ctx: &RequestContext) -> Result<T, Error> {
89 let raw = ctx.query_string().unwrap_or("");
90 serde_urlencoded::from_str::<T>(raw).map_err(|_| Error::BadRequest("invalid query string"))
91}
92
93#[inline]
94pub fn extract_body_json<T: DeserializeOwned>(ctx: &RequestContext) -> Result<T, Error> {
95 serde_json::from_slice::<T>(ctx.body()).map_err(|_| Error::BadRequest("invalid JSON body"))
96}
97
98#[inline]
99pub fn extract_header<'a>(ctx: &'a RequestContext, name: &'static str) -> Result<&'a str, Error> {
100 ctx.header(name)
101 .ok_or(Error::BadRequest("missing required header"))
102}
103
104#[inline]
111pub fn extract_body_validated<T: DeserializeOwned + Validate>(
112 ctx: &RequestContext,
113) -> Result<T, Error> {
114 let v: T = extract_body_json(ctx)?;
115 v.validate().map_err(Error::from)?;
116 Ok(v)
117}
118
119#[inline]
120pub fn extract_query_validated<T: DeserializeOwned + Validate>(
121 ctx: &RequestContext,
122) -> Result<T, Error> {
123 let v: T = extract_query(ctx)?;
124 v.validate().map_err(Error::from)?;
125 Ok(v)
126}