1use std::{collections::HashMap, future::Future, rc::Rc};
2
3use futures_util::future::LocalBoxFuture;
4use matchit::{Match, Router as MatchItRouter};
5use worker_kv::KvStore;
6
7use crate::{
8 durable::ObjectNamespace,
9 env::{Env, Secret, Var},
10 http::Method,
11 request::Request,
12 response::Response,
13 Bucket, Fetcher, Result,
14};
15
16type HandlerFn<D> = fn(Request, RouteContext<D>) -> Result<Response>;
17type AsyncHandlerFn<'a, D> =
18 Rc<dyn 'a + Fn(Request, RouteContext<D>) -> LocalBoxFuture<'a, Result<Response>>>;
19
20pub struct RouteParams(HashMap<String, String>);
23
24impl RouteParams {
25 fn get(&self, key: &str) -> Option<&String> {
26 self.0.get(key)
27 }
28}
29
30enum Handler<'a, D> {
31 Async(AsyncHandlerFn<'a, D>),
32 Sync(HandlerFn<D>),
33}
34
35impl<D> Clone for Handler<'_, D> {
36 fn clone(&self) -> Self {
37 match self {
38 Self::Async(rc) => Self::Async(rc.clone()),
39 Self::Sync(func) => Self::Sync(*func),
40 }
41 }
42}
43
44pub struct Router<'a, D> {
46 handlers: HashMap<Method, MatchItRouter<Handler<'a, D>>>,
47 or_else_any_method: MatchItRouter<Handler<'a, D>>,
48 data: D,
49}
50
51pub struct RouteContext<D> {
54 pub data: D,
55 pub env: Env,
56 params: RouteParams,
57}
58
59impl<D> RouteContext<D> {
60 #[deprecated(since = "0.0.8", note = "please use the `data` field directly")]
62 pub fn data(&self) -> &D {
63 &self.data
64 }
65
66 #[deprecated(since = "0.0.8", note = "please use the `env` field directly")]
69 pub fn get_env(self) -> Env {
70 self.env
71 }
72
73 pub fn secret(&self, binding: &str) -> Result<Secret> {
75 self.env.secret(binding)
76 }
77
78 pub fn var(&self, binding: &str) -> Result<Var> {
80 self.env.var(binding)
81 }
82
83 pub fn kv(&self, binding: &str) -> Result<KvStore> {
85 KvStore::from_this(&self.env, binding).map_err(From::from)
86 }
87
88 pub fn durable_object(&self, binding: &str) -> Result<ObjectNamespace> {
90 self.env.durable_object(binding)
91 }
92
93 pub fn param(&self, key: &str) -> Option<&String> {
95 self.params.get(key)
96 }
97
98 pub fn service(&self, binding: &str) -> Result<Fetcher> {
101 self.env.service(binding)
102 }
103
104 pub fn bucket(&self, binding: &str) -> Result<Bucket> {
106 self.env.bucket(binding)
107 }
108
109 #[cfg(feature = "d1")]
111 pub fn d1(&self, binding: &str) -> Result<crate::D1Database> {
112 self.env.d1(binding)
113 }
114}
115
116impl Router<'_, ()> {
117 pub fn new() -> Self {
120 Self::with_data(())
121 }
122}
123
124impl<'a, D: 'a> Router<'a, D> {
125 pub fn with_data(data: D) -> Self {
127 Self {
128 handlers: HashMap::new(),
129 or_else_any_method: MatchItRouter::new(),
130 data,
131 }
132 }
133
134 pub fn head(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
136 self.add_handler(pattern, Handler::Sync(func), vec![Method::Head]);
137 self
138 }
139
140 pub fn get(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
142 self.add_handler(pattern, Handler::Sync(func), vec![Method::Get]);
143 self
144 }
145
146 pub fn post(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
148 self.add_handler(pattern, Handler::Sync(func), vec![Method::Post]);
149 self
150 }
151
152 pub fn put(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
154 self.add_handler(pattern, Handler::Sync(func), vec![Method::Put]);
155 self
156 }
157
158 pub fn patch(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
160 self.add_handler(pattern, Handler::Sync(func), vec![Method::Patch]);
161 self
162 }
163
164 pub fn delete(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
166 self.add_handler(pattern, Handler::Sync(func), vec![Method::Delete]);
167 self
168 }
169
170 pub fn options(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
172 self.add_handler(pattern, Handler::Sync(func), vec![Method::Options]);
173 self
174 }
175
176 pub fn report(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
178 self.add_handler(pattern, Handler::Sync(func), vec![Method::Report]);
179 self
180 }
181
182 pub fn on(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
184 self.add_handler(pattern, Handler::Sync(func), Method::all());
185 self
186 }
187
188 pub fn or_else_any_method(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
191 self.or_else_any_method
192 .insert(pattern, Handler::Sync(func))
193 .unwrap_or_else(|e| panic!("failed to register route for {} pattern: {}", pattern, e));
194 self
195 }
196
197 pub fn head_async<T>(
200 mut self,
201 pattern: &str,
202 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
203 ) -> Self
204 where
205 T: Future<Output = Result<Response>> + 'a,
206 {
207 self.add_handler(
208 pattern,
209 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
210 vec![Method::Head],
211 );
212 self
213 }
214
215 pub fn get_async<T>(
218 mut self,
219 pattern: &str,
220 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
221 ) -> Self
222 where
223 T: Future<Output = Result<Response>> + 'a,
224 {
225 self.add_handler(
226 pattern,
227 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
228 vec![Method::Get],
229 );
230 self
231 }
232
233 pub fn post_async<T>(
236 mut self,
237 pattern: &str,
238 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
239 ) -> Self
240 where
241 T: Future<Output = Result<Response>> + 'a,
242 {
243 self.add_handler(
244 pattern,
245 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
246 vec![Method::Post],
247 );
248 self
249 }
250
251 pub fn put_async<T>(
254 mut self,
255 pattern: &str,
256 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
257 ) -> Self
258 where
259 T: Future<Output = Result<Response>> + 'a,
260 {
261 self.add_handler(
262 pattern,
263 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
264 vec![Method::Put],
265 );
266 self
267 }
268
269 pub fn patch_async<T>(
272 mut self,
273 pattern: &str,
274 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
275 ) -> Self
276 where
277 T: Future<Output = Result<Response>> + 'a,
278 {
279 self.add_handler(
280 pattern,
281 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
282 vec![Method::Patch],
283 );
284 self
285 }
286
287 pub fn delete_async<T>(
290 mut self,
291 pattern: &str,
292 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
293 ) -> Self
294 where
295 T: Future<Output = Result<Response>> + 'a,
296 {
297 self.add_handler(
298 pattern,
299 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
300 vec![Method::Delete],
301 );
302 self
303 }
304
305 pub fn options_async<T>(
308 mut self,
309 pattern: &str,
310 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
311 ) -> Self
312 where
313 T: Future<Output = Result<Response>> + 'a,
314 {
315 self.add_handler(
316 pattern,
317 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
318 vec![Method::Options],
319 );
320 self
321 }
322
323 pub fn on_async<T>(
326 mut self,
327 pattern: &str,
328 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
329 ) -> Self
330 where
331 T: Future<Output = Result<Response>> + 'a,
332 {
333 self.add_handler(
334 pattern,
335 Handler::Async(Rc::new(move |req, route| Box::pin(func(req, route)))),
336 Method::all(),
337 );
338 self
339 }
340
341 pub fn or_else_any_method_async<T>(
344 mut self,
345 pattern: &str,
346 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
347 ) -> Self
348 where
349 T: Future<Output = Result<Response>> + 'a,
350 {
351 self.or_else_any_method
352 .insert(
353 pattern,
354 Handler::Async(Rc::new(move |req, route| Box::pin(func(req, route)))),
355 )
356 .unwrap_or_else(|e| panic!("failed to register route for {} pattern: {}", pattern, e));
357 self
358 }
359
360 fn add_handler(&mut self, pattern: &str, func: Handler<'a, D>, methods: Vec<Method>) {
361 for method in methods {
362 self.handlers
363 .entry(method.clone())
364 .or_default()
365 .insert(pattern, func.clone())
366 .unwrap_or_else(|e| {
367 panic!(
368 "failed to register {:?} route for {} pattern: {}",
369 method, pattern, e
370 )
371 });
372 }
373 }
374
375 pub async fn run(self, req: Request, env: Env) -> Result<Response> {
377 let (handlers, data, or_else_any_method_handler) = self.split();
378
379 if let Some(handlers) = handlers.get(&req.method()) {
380 if let Ok(Match { value, params }) = handlers.at(&req.path()) {
381 let route_info = RouteContext {
382 data,
383 env,
384 params: params.into(),
385 };
386 return match value {
387 Handler::Sync(func) => (func)(req, route_info),
388 Handler::Async(func) => (func)(req, route_info).await,
389 };
390 }
391 }
392
393 for method in Method::all() {
394 if method == Method::Head || method == Method::Options || method == Method::Trace {
395 continue;
396 }
397 if let Some(handlers) = handlers.get(&method) {
398 if let Ok(Match { .. }) = handlers.at(&req.path()) {
399 return Response::error("Method Not Allowed", 405);
400 }
401 }
402 }
403
404 if let Ok(Match { value, params }) = or_else_any_method_handler.at(&req.path()) {
405 let route_info = RouteContext {
406 data,
407 env,
408 params: params.into(),
409 };
410 return match value {
411 Handler::Sync(func) => (func)(req, route_info),
412 Handler::Async(func) => (func)(req, route_info).await,
413 };
414 }
415
416 Response::error("Not Found", 404)
417 }
418}
419
420type NodeWithHandlers<'a, D> = MatchItRouter<Handler<'a, D>>;
421
422impl<'a, D: 'a> Router<'a, D> {
423 fn split(
424 self,
425 ) -> (
426 HashMap<Method, NodeWithHandlers<'a, D>>,
427 D,
428 NodeWithHandlers<'a, D>,
429 ) {
430 (self.handlers, self.data, self.or_else_any_method)
431 }
432}
433
434impl From<matchit::Params<'_, '_>> for RouteParams {
435 fn from(p: matchit::Params) -> Self {
436 let mut route_params = RouteParams(HashMap::new());
437 for (ident, value) in p.iter() {
438 route_params.0.insert(ident.into(), value.into());
439 }
440
441 route_params
442 }
443}