gotham/router/route/
dispatch.rs1use futures_util::future::{self, FutureExt};
4use log::trace;
5use std::panic::RefUnwindSafe;
6use std::pin::Pin;
7
8use crate::handler::{Handler, HandlerFuture, NewHandler};
9use crate::pipeline::{PipelineHandleChain, PipelineSet};
10use crate::state::{request_id, State};
11
12pub trait Dispatcher: RefUnwindSafe {
14 fn dispatch(&self, state: State) -> Pin<Box<HandlerFuture>>;
16}
17
18pub struct DispatcherImpl<H, C, P>
20where
21 H: NewHandler,
22 C: PipelineHandleChain<P>,
23 P: RefUnwindSafe,
24{
25 new_handler: H,
26 pipeline_chain: C,
27 pipelines: PipelineSet<P>,
28}
29
30impl<H, C, P> DispatcherImpl<H, C, P>
31where
32 H: NewHandler,
33 H::Instance: 'static,
34 C: PipelineHandleChain<P>,
35 P: RefUnwindSafe,
36{
37 pub fn new(new_handler: H, pipeline_chain: C, pipelines: PipelineSet<P>) -> Self {
45 DispatcherImpl {
46 new_handler,
47 pipeline_chain,
48 pipelines,
49 }
50 }
51}
52
53impl<H, C, P> Dispatcher for DispatcherImpl<H, C, P>
54where
55 H: NewHandler,
56 H::Instance: Send + 'static,
57 C: PipelineHandleChain<P>,
58 P: RefUnwindSafe,
59{
60 fn dispatch(&self, state: State) -> Pin<Box<HandlerFuture>> {
61 match self.new_handler.new_handler() {
62 Ok(h) => {
63 trace!("[{}] cloning handler", request_id(&state));
64 self.pipeline_chain
65 .call(&self.pipelines, state, move |state| h.handle(state))
66 }
67 Err(e) => {
68 trace!("[{}] error cloning handler", request_id(&state));
69 future::err((state, e.into())).boxed()
70 }
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use std::sync::Arc;
79
80 use hyper::{Body, Response, StatusCode};
81
82 use crate::middleware::{Middleware, NewMiddleware};
83 use crate::pipeline::{new_pipeline, new_pipeline_set};
84 use crate::state::StateData;
85 use crate::test::TestServer;
86
87 fn handler(state: State) -> (State, Response<Body>) {
88 let number = state.borrow::<Number>().value;
89 (
90 state,
91 Response::builder()
92 .status(StatusCode::OK)
93 .body(format!("{}", number).into())
94 .unwrap(),
95 )
96 }
97
98 #[derive(Clone)]
99 struct Number {
100 value: i32,
101 }
102
103 impl NewMiddleware for Number {
104 type Instance = Number;
105
106 fn new_middleware(&self) -> anyhow::Result<Number> {
107 Ok(self.clone())
108 }
109 }
110
111 impl Middleware for Number {
112 fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
113 where
114 Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
115 Self: Sized,
116 {
117 state.put(self);
118 chain(state)
119 }
120 }
121
122 impl StateData for Number {}
123
124 struct Addition {
125 value: i32,
126 }
127
128 impl NewMiddleware for Addition {
129 type Instance = Addition;
130
131 fn new_middleware(&self) -> anyhow::Result<Addition> {
132 Ok(Addition { ..*self })
133 }
134 }
135
136 impl Middleware for Addition {
137 fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
138 where
139 Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
140 Self: Sized,
141 {
142 state.borrow_mut::<Number>().value += self.value;
143 chain(state)
144 }
145 }
146
147 struct Multiplication {
148 value: i32,
149 }
150
151 impl NewMiddleware for Multiplication {
152 type Instance = Multiplication;
153
154 fn new_middleware(&self) -> anyhow::Result<Multiplication> {
155 Ok(Multiplication { ..*self })
156 }
157 }
158
159 impl Middleware for Multiplication {
160 fn call<Chain>(self, mut state: State, chain: Chain) -> Pin<Box<HandlerFuture>>
161 where
162 Chain: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
163 Self: Sized,
164 {
165 state.borrow_mut::<Number>().value *= self.value;
166 chain(state)
167 }
168 }
169
170 #[test]
171 fn pipeline_chain_ordering_test() {
172 let test_server = TestServer::new(|| {
173 Ok(move |state| {
174 let pipelines = new_pipeline_set();
175
176 let (pipelines, p1) = pipelines.add(
177 new_pipeline()
178 .add(Number { value: 0 }) .add(Addition { value: 1 }) .add(Multiplication { value: 2 }) .build(),
182 );
183
184 let (pipelines, p2) = pipelines.add(
185 new_pipeline()
186 .add(Addition { value: 1 }) .add(Multiplication { value: 2 }) .build(),
189 );
190
191 let (pipelines, p3) = pipelines.add(
192 new_pipeline()
193 .add(Addition { value: 2 }) .add(Multiplication { value: 3 }) .build(),
196 );
197
198 let pipelines = Arc::new(pipelines);
199
200 let new_handler = || Ok(handler);
201
202 let pipeline_chain = (p3, (p2, (p1, ())));
203 let dispatcher = DispatcherImpl::new(new_handler, pipeline_chain, pipelines);
204 dispatcher.dispatch(state)
205 })
206 })
207 .unwrap();
208
209 let response = test_server
210 .client()
211 .get("http://localhost/")
212 .perform()
213 .unwrap();
214
215 let buf = response.read_body().unwrap();
216 assert_eq!(buf.as_slice(), b"24");
217 }
218}