alux_http_actix/
handler.rs1use crate::input::{
4 ActixBodyInput, ActixCookieInput, ActixFormInput, ActixHeaderInput, ActixInputsAlg, ActixMultipartInput,
5 ActixPathInput, ActixQueryInput, ActixRequestInput,
6};
7use crate::route::{ActixEndpoint, ActixRoute, ActixRouteImpl, ActixSelector};
8use actix_web::web::Payload;
9use actix_web::{HttpRequest, HttpResponse, Route};
10use alux_ext::{ApplyAlg, HandlerContextAlg, OperationAlg};
11use alux_http::{
12 HandlerAlg, HandlerEndpointAlg, HttpInputAlg, HttpMethod, HttpSelectorAlg, OutputAlg, OutputKindAlg, RouteAlg,
13 RoutePath, SelectorAlg,
14};
15use std::sync::Arc;
16
17pub struct ActixHandlerImpl<Context> {
23 context: Arc<Context>,
24}
25
26impl<Context> ActixHandlerImpl<Context> {
27 pub fn new(context: Context) -> Self {
29 Self { context: Arc::new(context) }
30 }
31
32 pub fn from_shared(context: Arc<Context>) -> Self {
34 Self { context }
35 }
36}
37
38impl<Context> HandlerContextAlg<Context> for ActixHandlerImpl<Context>
39where
40 Context: Send + Sync + 'static,
41{
42 type Handle = Arc<Context>;
43}
44
45impl<Context> HandlerAlg for ActixHandlerImpl<Context> {
46 type Endpoint = ActixEndpoint;
47}
48
49impl<Context> HttpInputAlg for ActixHandlerImpl<Context> {
50 type Path<I> = ActixPathInput<I>;
51 type Query<I> = ActixQueryInput<I>;
52 type Body<I> = ActixBodyInput<I>;
53 type Form<I> = ActixFormInput<I>;
54 type Multipart<I> = ActixMultipartInput<I>;
55 type RawBody<I> = ActixRequestInput<I>;
58 type Header<I> = ActixHeaderInput<I>;
59 type Cookie<I> = ActixCookieInput<I>;
60 type Auth<I> = ActixHeaderInput<I>;
61 type Context<I> = ActixRequestInput<I>;
62}
63
64impl<Context, Inputs, Args, Transform, Answering, Output>
65 HandlerEndpointAlg<Arc<Context>, Inputs, Args, Transform, Output> for ActixHandlerImpl<Context>
66where
67 Context: Send + Sync + 'static,
68 Inputs: ActixInputsAlg<Args> + 'static,
69 Args: 'static,
70 Output: 'static,
71 Transform: OutputKindAlg<Self, Output, Transform = Answering> + 'static,
72 Answering: OutputAlg<Output, Output = HttpResponse>,
73{
74 fn finish_handler<Handler>(&self, handler: Handler) -> <Self as HandlerAlg>::Endpoint
75 where
76 Handler: OperationAlg + ApplyAlg<Arc<Context>, Args, Output = Output> + Send + Sync + 'static,
77 {
78 let context = Arc::clone(&self.context);
79 let handler = Arc::new(handler);
80
81 ActixEndpoint::new(move || {
83 let context = Arc::clone(&context);
84 let handler = Arc::clone(&handler);
85
86 Route::new().to(move |request: HttpRequest, payload: Payload| {
87 let context = Arc::clone(&context);
88 let handler = Arc::clone(&handler);
89 async move {
90 let mut payload = payload.into_inner();
92 let inputs = match Inputs::extract(&request, &mut payload).await {
93 Ok(inputs) => inputs,
94 Err(rejection) => return rejection.error_response(),
95 };
96 let output = handler.apply(context, inputs).await;
97
98 Answering::output(output)
99 }
100 })
101 })
102 }
103}
104
105impl<Context> SelectorAlg for ActixHandlerImpl<Context> {
106 type Selector = ActixSelector;
107
108 fn identity(&self) -> Self::Selector {
109 SelectorAlg::identity(&ActixRouteImpl)
110 }
111
112 fn compose(&self, first: Self::Selector, second: Self::Selector) -> Self::Selector {
113 SelectorAlg::compose(&ActixRouteImpl, first, second)
114 }
115}
116
117impl<Context> RouteAlg for ActixHandlerImpl<Context> {
118 type Route = ActixRoute;
119 type Selector = ActixSelector;
120 type Endpoint = ActixEndpoint;
121
122 fn initial(&self) -> Self::Route {
123 RouteAlg::initial(&ActixRouteImpl)
124 }
125
126 fn coproduct(&self, left: Self::Route, right: Self::Route) -> Self::Route {
127 RouteAlg::coproduct(&ActixRouteImpl, left, right)
128 }
129
130 fn precompose(&self, selector: Self::Selector, route: Self::Route) -> Self::Route {
131 RouteAlg::precompose(&ActixRouteImpl, selector, route)
132 }
133
134 fn lift(&self, endpoint: Self::Endpoint) -> Self::Route {
135 RouteAlg::lift(&ActixRouteImpl, endpoint)
136 }
137}
138
139impl<Context> HttpSelectorAlg for ActixHandlerImpl<Context> {
140 type Selector = ActixSelector;
141
142 fn http_method(&self, method: HttpMethod) -> Self::Selector {
143 HttpSelectorAlg::http_method(&ActixRouteImpl, method)
144 }
145
146 fn http_path(&self, path: &RoutePath) -> Self::Selector {
147 HttpSelectorAlg::http_path(&ActixRouteImpl, path)
148 }
149
150 fn http_prefix(&self, prefix: &RoutePath) -> Self::Selector {
151 HttpSelectorAlg::http_prefix(&ActixRouteImpl, prefix)
152 }
153}