a3s_boot/routing/route/
execution.rs1use super::definition::RouteDefinition;
2use crate::routing::path::{join_paths, route_shape_key, route_specificity};
3use crate::{BootError, BootRequest, BootResponse, ExecutionContext, MiddlewareOutcome, Result};
4
5impl RouteDefinition {
6 pub async fn call(&self, mut request: BootRequest) -> Result<BootResponse> {
7 if !self.method.matches(request.method) {
8 let message = format!("{} {}", request.method.as_str(), request.path);
9 return self
10 .handle_error(
11 self.execution_context(request),
12 BootError::MethodNotAllowed(message),
13 )
14 .await;
15 }
16
17 let params = match self.path_params(&request.path) {
18 Ok(Some(params)) => params,
19 Ok(None) => {
20 let message = format!("{} {}", request.method.as_str(), request.path);
21 return self
22 .handle_error(
23 self.execution_context(request),
24 BootError::NotFound(message),
25 )
26 .await;
27 }
28 Err(error) => {
29 return self
30 .handle_error(self.execution_context(request), error)
31 .await;
32 }
33 };
34 request = request.with_path_params(params);
35 let host_params = match self.host_params(request.host()) {
36 Ok(Some(params)) => params,
37 Ok(None) => {
38 let message = format!("{} {}", request.method.as_str(), request.path);
39 return self
40 .handle_error(
41 self.execution_context(request),
42 BootError::NotFound(message),
43 )
44 .await;
45 }
46 Err(error) => {
47 return self
48 .handle_error(self.execution_context(request), error)
49 .await;
50 }
51 };
52 request = request.with_host_params(host_params);
53 if let Some(module_ref) = &self.module_ref {
54 request = request.with_module_ref(module_ref.request_scope());
55 }
56
57 #[cfg(feature = "request-context")]
58 {
59 let context = crate::RequestContext::from_route_request(
60 &request,
61 self.path.clone(),
62 self.module_name.clone(),
63 self.controller_prefix.clone(),
64 self.metadata.clone(),
65 );
66 return crate::RequestContext::scope(context, self.call_pipeline(request)).await;
67 }
68
69 #[cfg(not(feature = "request-context"))]
70 {
71 self.call_pipeline(request).await
72 }
73 }
74
75 async fn call_pipeline(&self, mut request: BootRequest) -> Result<BootResponse> {
76 for middleware in &self.middleware {
77 let context_request = request.clone();
78 request = match middleware.handle(request).await {
79 Ok(MiddlewareOutcome::Continue(request)) => request,
80 Ok(MiddlewareOutcome::Respond(response)) => return Ok(response),
81 Err(error) => {
82 return self
83 .handle_error(self.execution_context(context_request), error)
84 .await;
85 }
86 };
87 }
88
89 let context = self.execution_context(request.clone());
90
91 for guard in &self.guards {
92 let can_activate = match guard.inner().can_activate(context.clone()).await {
93 Ok(can_activate) => can_activate,
94 Err(error) => return self.handle_error(context.clone(), error).await,
95 };
96
97 if !can_activate {
98 let message = format!("{} {}", context.method.as_str(), context.request_path);
99 return self
100 .handle_error(context, BootError::Forbidden(message))
101 .await;
102 }
103 }
104
105 for (index, interceptor) in self.interceptors.iter().enumerate() {
106 if let Err(error) = interceptor.inner().before(context.clone()).await {
107 return self.handle_error(context.clone(), error).await;
108 }
109
110 let mut response = match interceptor.inner().short_circuit(context.clone()).await {
111 Ok(Some(response)) => response,
112 Ok(None) => continue,
113 Err(error) => return self.handle_error(context.clone(), error).await,
114 };
115
116 for interceptor in self.interceptors[..index].iter().rev() {
117 response = match interceptor.inner().after(context.clone(), response).await {
118 Ok(response) => response,
119 Err(error) => return self.handle_error(context.clone(), error).await,
120 };
121 }
122
123 return Ok(response);
124 }
125
126 for pipe in &self.pipes {
127 let context_request = request.clone();
128 request = match pipe.inner().transform(request).await {
129 Ok(request) => request,
130 Err(error) => {
131 return self
132 .handle_error(self.execution_context(context_request), error)
133 .await;
134 }
135 };
136 }
137
138 if self.validation_enabled {
139 for validator in &self.validators {
140 let context_request = request.clone();
141 request = match validator(request, self.validation_options) {
142 Ok(request) => request,
143 Err(error) => {
144 return self
145 .handle_error(self.execution_context(context_request), error)
146 .await;
147 }
148 };
149 }
150 }
151
152 let mut response = match self.handler.call(request).await {
153 Ok(response) => response,
154 Err(error) => return self.handle_error(context, error).await,
155 };
156
157 for interceptor in self.interceptors.iter().rev() {
158 response = match interceptor.inner().after(context.clone(), response).await {
159 Ok(response) => response,
160 Err(error) => return self.handle_error(context.clone(), error).await,
161 };
162 }
163
164 Ok(response)
165 }
166
167 pub async fn handle(&self, request: BootRequest) -> BootResponse {
169 match self.call(request).await {
170 Ok(response) => response,
171 Err(error) => BootResponse::from_error(&error),
172 }
173 }
174
175 pub(crate) fn matches_path_shape(&self, path: &str) -> bool {
176 self.matches_path(path)
177 }
178
179 pub(crate) fn path_shape_key(&self) -> String {
180 route_shape_key(&self.path)
181 }
182
183 pub(crate) fn path_specificity(&self) -> Vec<u8> {
184 route_specificity(&self.path)
185 }
186
187 fn execution_context(&self, request: BootRequest) -> ExecutionContext {
188 ExecutionContext::new(
189 request,
190 self.path.clone(),
191 self.module_name.clone(),
192 self.controller_prefix.clone(),
193 self.serialization.clone(),
194 self.metadata.clone(),
195 )
196 }
197
198 pub(crate) fn with_prefix(mut self, prefix: &str) -> Result<Self> {
199 self.path = join_paths(prefix, &self.path)?;
200 self.controller_prefix = Some(prefix.trim_end_matches('/').to_string());
201 Ok(self)
202 }
203
204 pub(crate) fn with_path_prefix(mut self, prefix: &str) -> Result<Self> {
205 self.path = join_paths(prefix, &self.path)?;
206 Ok(self)
207 }
208
209 pub(crate) fn with_module_name(mut self, module_name: &str) -> Self {
210 self.module_name = Some(module_name.to_string());
211 self
212 }
213
214 pub(crate) fn with_module_ref(mut self, module_ref: crate::ModuleRef) -> Self {
215 self.module_ref = Some(module_ref);
216 self
217 }
218
219 pub(crate) fn with_default_module_ref(mut self, module_ref: crate::ModuleRef) -> Self {
220 if self.module_ref.is_none() {
221 self.module_ref = Some(module_ref);
222 }
223 self
224 }
225
226 async fn handle_error(
227 &self,
228 context: ExecutionContext,
229 error: BootError,
230 ) -> Result<BootResponse> {
231 for filter in self.filters.iter().rev() {
232 if let Some(response) = filter
233 .inner()
234 .catch(context.clone(), error.clone_for_filter())
235 .await?
236 {
237 return Ok(response);
238 }
239 }
240 Err(error)
241 }
242}