1use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe};
5
6use futures_util::future::FutureExt;
7use hyper::{Body, Response, StatusCode};
8use log::error;
9
10use crate::handler::{Handler, HandlerError, IntoResponse, NewHandler};
11use crate::state::{request_id, State};
12
13async fn handle<H>(
14 handler: H,
15 state: AssertUnwindSafe<State>,
16) -> Result<(State, Response<Body>), (State, HandlerError)>
17where
18 H: Handler,
19{
20 let AssertUnwindSafe(state) = state;
21 handler.handle(state).await
22}
23
24pub async fn call_handler<T>(t: T, state: AssertUnwindSafe<State>) -> anyhow::Result<Response<Body>>
31where
32 T: NewHandler + Send + UnwindSafe,
33{
34 match catch_unwind(move || t.new_handler()) {
35 Ok(handler) => {
36 let unwind_result = AssertUnwindSafe(handle(handler?, state))
37 .catch_unwind()
38 .await;
39 let result = match unwind_result {
40 Ok(result) => result.map(|(_, res)| res),
41 Err(_) => Ok(finalize_panic_response()),
42 };
43 Ok(match result {
44 Ok(res) => res,
45 Err((state, err)) => finalize_error_response(state, err),
46 })
47 }
48 Err(_) => Ok(finalize_panic_response()),
50 }
51}
52
53fn finalize_error_response(state: State, err: HandlerError) -> Response<Body> {
54 error!("[ERROR][{}][Error: {:?}]", request_id(&state), err);
55
56 err.into_response(&state)
57}
58
59fn finalize_panic_response() -> Response<Body> {
60 error!("[PANIC][A panic occurred while invoking the handler]");
61
62 Response::builder()
63 .status(StatusCode::INTERNAL_SERVER_ERROR)
64 .body(Body::default())
65 .unwrap()
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 use futures_util::future;
73 use hyper::{HeaderMap, Method, StatusCode};
74 use std::io;
75 use std::pin::Pin;
76
77 use crate::handler::HandlerFuture;
78 use crate::helpers::http::response::create_empty_response;
79 use crate::state::set_request_id;
80
81 #[test]
82 fn success() {
83 let new_handler = || {
84 Ok(|state| {
85 let res = create_empty_response(&state, StatusCode::ACCEPTED);
86 (state, res)
87 })
88 };
89
90 let mut state = State::new();
91 state.put(HeaderMap::new());
92 state.put(Method::GET);
93 set_request_id(&mut state);
94
95 let r = call_handler(&new_handler, AssertUnwindSafe(state));
96 let response = futures_executor::block_on(r).unwrap();
97 assert_eq!(response.status(), StatusCode::ACCEPTED);
98 }
99
100 #[test]
101 fn async_success_repeat_poll() {
102 let new_handler = || {
103 Ok(|state| {
104 let f = future::lazy(move |_| {
105 let res = create_empty_response(&state, StatusCode::ACCEPTED);
106 Ok((state, res))
107 });
108
109 let f = f.map(|v| v);
110 let f = f.map(|v| v);
111 let f = f.map(|v| v);
112
113 f.boxed()
114 })
115 };
116
117 let mut state = State::new();
118 state.put(HeaderMap::new());
119 state.put(Method::GET);
120 set_request_id(&mut state);
121
122 let r = call_handler(&new_handler, AssertUnwindSafe(state));
123 let response = futures_executor::block_on(r).unwrap();
124 assert_eq!(response.status(), StatusCode::ACCEPTED);
125 }
126
127 #[test]
128 fn error() {
129 let new_handler =
130 || Ok(|state| future::err((state, io::Error::last_os_error().into())).boxed());
131
132 let mut state = State::new();
133 state.put(HeaderMap::new());
134 state.put(Method::GET);
135 set_request_id(&mut state);
136
137 let r = call_handler(&new_handler, AssertUnwindSafe(state));
138 let response = futures_executor::block_on(r).unwrap();
139 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
140 }
141
142 #[test]
143 fn panic() {
144 #[allow(clippy::unnecessary_literal_unwrap)] let new_handler = || {
146 Ok(|_| {
147 let val: Option<Pin<Box<HandlerFuture>>> = None;
148 val.expect("test panic")
149 })
150 };
151
152 let mut state = State::new();
153 state.put(HeaderMap::new());
154 state.put(Method::GET);
155 set_request_id(&mut state);
156
157 let r = call_handler(&new_handler, AssertUnwindSafe(state));
158 let response = futures_executor::block_on(r).unwrap();
159 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
160 }
161
162 #[test]
163 fn async_panic() {
164 let new_handler = || Ok(|_| future::lazy(move |_| panic!("test panic")).boxed());
165
166 let mut state = State::new();
167 state.put(HeaderMap::new());
168 state.put(Method::GET);
169 set_request_id(&mut state);
170
171 let r = call_handler(&new_handler, AssertUnwindSafe(state));
172 let response = futures_executor::block_on(r).unwrap();
173 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
174 }
175
176 #[test]
177 fn async_panic_repeat_poll() {
178 let new_handler = || {
179 Ok(|_| {
180 let f = future::lazy(move |_| panic!("test panic"));
181
182 let f = f.map(|v| v);
183 let f = f.map(|v| v);
184 let f = f.map(|v| v);
185
186 f.boxed()
187 })
188 };
189
190 let mut state = State::new();
191 state.put(HeaderMap::new());
192 state.put(Method::GET);
193 set_request_id(&mut state);
194
195 let r = call_handler(&new_handler, AssertUnwindSafe(state));
196 let response = futures_executor::block_on(r).unwrap();
197 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
198 }
199
200 #[test]
201 fn new_handler_panic() {
202 struct PanicNewHandler;
203 impl NewHandler for PanicNewHandler {
204 type Instance = Self;
205
206 fn new_handler(&self) -> anyhow::Result<Self::Instance> {
207 panic!("Pannicked creating a new handler");
208 }
209 }
210
211 impl Handler for PanicNewHandler {
212 fn handle(self, _state: State) -> Pin<Box<HandlerFuture>> {
213 unreachable!();
214 }
215 }
216
217 let mut state = State::new();
218 state.put(HeaderMap::new());
219 state.put(Method::GET);
220 set_request_id(&mut state);
221
222 let new_handler = PanicNewHandler {};
223 let r = call_handler(new_handler, AssertUnwindSafe(state));
224 let response = futures_executor::block_on(r).unwrap();
225 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
226 }
227}