alux_http_rocket/
handler.rs1use crate::RocketAnswer;
4use crate::input::{
5 RocketBodyInput, RocketCookieInput, RocketFormInput, RocketHeadInput, RocketHeaderInput, RocketInputsAlg,
6 RocketMultipartInput, RocketPathInput, RocketQueryInput, RocketRawBodyInput,
7};
8use crate::route::{RocketEndpoint, RocketRoute, RocketRouteImpl, RocketSelector};
9use alux_ext::{ApplyAlg, HandlerContextAlg, OperationAlg};
10use alux_http::{
11 HandlerAlg, HandlerEndpointAlg, HttpErrorAlg, HttpInputAlg, HttpMethod, HttpSelectorAlg, OutputAlg, OutputKindAlg,
12 RouteAlg, RoutePath, SelectorAlg,
13};
14use std::sync::Arc;
15
16pub struct RocketHandlerImpl<Context> {
18 context: Arc<Context>,
19}
20
21impl<Context> RocketHandlerImpl<Context> {
22 pub fn new(context: Context) -> Self {
24 Self { context: Arc::new(context) }
25 }
26
27 pub fn from_shared(context: Arc<Context>) -> Self {
29 Self { context }
30 }
31}
32
33impl<Context> HandlerContextAlg<Context> for RocketHandlerImpl<Context>
34where
35 Context: Send + Sync + 'static,
36{
37 type Handle = Arc<Context>;
38}
39
40impl<Context> HandlerAlg for RocketHandlerImpl<Context> {
41 type Endpoint = RocketEndpoint;
42}
43
44impl<Context> HttpInputAlg for RocketHandlerImpl<Context> {
45 type Path<I> = RocketPathInput<I>;
46 type Query<I> = RocketQueryInput<I>;
47 type Body<I> = RocketBodyInput<I>;
48 type Form<I> = RocketFormInput<I>;
49 type Multipart<I> = RocketMultipartInput<I>;
50 type RawBody<I> = RocketRawBodyInput<I>;
51 type Header<I> = RocketHeaderInput<I>;
53 type Cookie<I> = RocketCookieInput<I>;
54 type Auth<I> = RocketHeaderInput<I>;
55 type Context<I> = RocketHeadInput<I>;
56}
57
58impl<Context, Inputs, Args, Transform, Answering, Output>
59 HandlerEndpointAlg<Arc<Context>, Inputs, Args, Transform, Output> for RocketHandlerImpl<Context>
60where
61 Context: Send + Sync + 'static,
62 Inputs: RocketInputsAlg<Args> + Send + 'static,
63 Args: Send + 'static,
64 Output: Send + 'static,
65 Transform: OutputKindAlg<Self, Output, Transform = Answering> + Send + 'static,
66 Answering: OutputAlg<Output, Output = RocketAnswer>,
67{
68 fn finish_handler<Handler>(&self, handler: Handler) -> <Self as HandlerAlg>::Endpoint
69 where
70 Handler: OperationAlg + ApplyAlg<Arc<Context>, Args, Output = Output> + Send + Sync + 'static,
71 {
72 let context = Arc::clone(&self.context);
73 let handler = Arc::new(handler);
74
75 RocketEndpoint::new(move |request| {
76 let context = Arc::clone(&context);
77 let handler = Arc::clone(&handler);
78 Box::pin(async move {
79 let inputs = match Inputs::extract(&request).await {
80 Ok(inputs) => inputs,
81 Err(error) => return unreadable(&error),
82 };
83 let output = handler.apply(context, inputs).await;
84
85 Answering::output(output)
86 })
87 })
88 }
89}
90
91fn unreadable(error: &impl HttpErrorAlg) -> RocketAnswer {
93 RocketAnswer::content(error.http_status(), "text/plain; charset=utf-8", error.http_message())
94}
95
96impl<Context> SelectorAlg for RocketHandlerImpl<Context> {
97 type Selector = RocketSelector;
98
99 fn identity(&self) -> Self::Selector {
100 SelectorAlg::identity(&RocketRouteImpl)
101 }
102
103 fn compose(&self, first: Self::Selector, second: Self::Selector) -> Self::Selector {
104 SelectorAlg::compose(&RocketRouteImpl, first, second)
105 }
106}
107
108impl<Context> RouteAlg for RocketHandlerImpl<Context> {
109 type Route = RocketRoute;
110 type Selector = RocketSelector;
111 type Endpoint = RocketEndpoint;
112
113 fn initial(&self) -> Self::Route {
114 RouteAlg::initial(&RocketRouteImpl)
115 }
116
117 fn coproduct(&self, left: Self::Route, right: Self::Route) -> Self::Route {
118 RouteAlg::coproduct(&RocketRouteImpl, left, right)
119 }
120
121 fn precompose(&self, selector: Self::Selector, route: Self::Route) -> Self::Route {
122 RouteAlg::precompose(&RocketRouteImpl, selector, route)
123 }
124
125 fn lift(&self, endpoint: Self::Endpoint) -> Self::Route {
126 RouteAlg::lift(&RocketRouteImpl, endpoint)
127 }
128}
129
130impl<Context> HttpSelectorAlg for RocketHandlerImpl<Context> {
131 type Selector = RocketSelector;
132
133 fn http_method(&self, method: HttpMethod) -> Self::Selector {
134 HttpSelectorAlg::http_method(&RocketRouteImpl, method)
135 }
136
137 fn http_path(&self, path: &RoutePath) -> Self::Selector {
138 HttpSelectorAlg::http_path(&RocketRouteImpl, path)
139 }
140
141 fn http_prefix(&self, prefix: &RoutePath) -> Self::Selector {
142 HttpSelectorAlg::http_prefix(&RocketRouteImpl, prefix)
143 }
144}