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
20#[derive(Debug)]
23pub struct RouteParams(HashMap<String, String>);
24
25impl RouteParams {
26 fn get(&self, key: &str) -> Option<&String> {
27 self.0.get(key)
28 }
29}
30
31enum Handler<'a, D> {
32 Async(AsyncHandlerFn<'a, D>),
33 Sync(HandlerFn<D>),
34}
35
36impl<D> Clone for Handler<'_, D> {
37 fn clone(&self) -> Self {
38 match self {
39 Self::Async(rc) => Self::Async(rc.clone()),
40 Self::Sync(func) => Self::Sync(*func),
41 }
42 }
43}
44
45pub struct Router<'a, D> {
47 handlers: HashMap<Method, MatchItRouter<Handler<'a, D>>>,
48 or_else_any_method: MatchItRouter<Handler<'a, D>>,
49 data: D,
50}
51
52impl core::fmt::Debug for Router<'_, ()> {
53 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 f.debug_struct("Router").finish()
55 }
56}
57
58#[derive(Debug)]
61pub struct RouteContext<D> {
62 pub data: D,
63 pub env: Env,
64 params: RouteParams,
65}
66
67impl<D> RouteContext<D> {
68 #[deprecated(since = "0.0.8", note = "please use the `data` field directly")]
70 pub fn data(&self) -> &D {
71 &self.data
72 }
73
74 #[deprecated(since = "0.0.8", note = "please use the `env` field directly")]
77 pub fn get_env(self) -> Env {
78 self.env
79 }
80
81 pub fn secret(&self, binding: &str) -> Result<Secret> {
83 self.env.secret(binding)
84 }
85
86 pub fn var(&self, binding: &str) -> Result<Var> {
88 self.env.var(binding)
89 }
90
91 pub fn kv(&self, binding: &str) -> Result<KvStore> {
93 KvStore::from_this(&self.env, binding).map_err(From::from)
94 }
95
96 pub fn durable_object(&self, binding: &str) -> Result<ObjectNamespace> {
98 self.env.durable_object(binding)
99 }
100
101 pub fn param(&self, key: &str) -> Option<&String> {
103 self.params.get(key)
104 }
105
106 pub fn service(&self, binding: &str) -> Result<Fetcher> {
109 self.env.service(binding)
110 }
111
112 pub fn bucket(&self, binding: &str) -> Result<Bucket> {
114 self.env.bucket(binding)
115 }
116
117 #[cfg(feature = "d1")]
119 pub fn d1(&self, binding: &str) -> Result<crate::D1Database> {
120 self.env.d1(binding)
121 }
122}
123
124impl Router<'_, ()> {
125 pub fn new() -> Self {
128 Self::with_data(())
129 }
130}
131
132impl<'a, D: 'a> Router<'a, D> {
133 pub fn with_data(data: D) -> Self {
135 Self {
136 handlers: HashMap::new(),
137 or_else_any_method: MatchItRouter::new(),
138 data,
139 }
140 }
141
142 pub fn head(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
144 self.add_handler(pattern, Handler::Sync(func), vec![Method::Head]);
145 self
146 }
147
148 pub fn get(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
150 self.add_handler(pattern, Handler::Sync(func), vec![Method::Get]);
151 self
152 }
153
154 pub fn post(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
156 self.add_handler(pattern, Handler::Sync(func), vec![Method::Post]);
157 self
158 }
159
160 pub fn put(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
162 self.add_handler(pattern, Handler::Sync(func), vec![Method::Put]);
163 self
164 }
165
166 pub fn patch(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
168 self.add_handler(pattern, Handler::Sync(func), vec![Method::Patch]);
169 self
170 }
171
172 pub fn delete(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
174 self.add_handler(pattern, Handler::Sync(func), vec![Method::Delete]);
175 self
176 }
177
178 pub fn options(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
180 self.add_handler(pattern, Handler::Sync(func), vec![Method::Options]);
181 self
182 }
183
184 pub fn report(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
186 self.add_handler(pattern, Handler::Sync(func), vec![Method::Report]);
187 self
188 }
189
190 pub fn on(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
192 self.add_handler(pattern, Handler::Sync(func), Method::all());
193 self
194 }
195
196 pub fn or_else_any_method(mut self, pattern: &str, func: HandlerFn<D>) -> Self {
199 self.or_else_any_method
200 .insert(pattern, Handler::Sync(func))
201 .unwrap_or_else(|e| panic!("failed to register route for {} pattern: {}", pattern, e));
202 self
203 }
204
205 pub fn head_async<T>(
208 mut self,
209 pattern: &str,
210 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
211 ) -> Self
212 where
213 T: Future<Output = Result<Response>> + 'a,
214 {
215 self.add_handler(
216 pattern,
217 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
218 vec![Method::Head],
219 );
220 self
221 }
222
223 pub fn get_async<T>(
226 mut self,
227 pattern: &str,
228 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
229 ) -> Self
230 where
231 T: Future<Output = Result<Response>> + 'a,
232 {
233 self.add_handler(
234 pattern,
235 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
236 vec![Method::Get],
237 );
238 self
239 }
240
241 pub fn post_async<T>(
244 mut self,
245 pattern: &str,
246 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
247 ) -> Self
248 where
249 T: Future<Output = Result<Response>> + 'a,
250 {
251 self.add_handler(
252 pattern,
253 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
254 vec![Method::Post],
255 );
256 self
257 }
258
259 pub fn put_async<T>(
262 mut self,
263 pattern: &str,
264 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
265 ) -> Self
266 where
267 T: Future<Output = Result<Response>> + 'a,
268 {
269 self.add_handler(
270 pattern,
271 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
272 vec![Method::Put],
273 );
274 self
275 }
276
277 pub fn patch_async<T>(
280 mut self,
281 pattern: &str,
282 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
283 ) -> Self
284 where
285 T: Future<Output = Result<Response>> + 'a,
286 {
287 self.add_handler(
288 pattern,
289 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
290 vec![Method::Patch],
291 );
292 self
293 }
294
295 pub fn delete_async<T>(
298 mut self,
299 pattern: &str,
300 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
301 ) -> Self
302 where
303 T: Future<Output = Result<Response>> + 'a,
304 {
305 self.add_handler(
306 pattern,
307 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
308 vec![Method::Delete],
309 );
310 self
311 }
312
313 pub fn options_async<T>(
316 mut self,
317 pattern: &str,
318 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
319 ) -> Self
320 where
321 T: Future<Output = Result<Response>> + 'a,
322 {
323 self.add_handler(
324 pattern,
325 Handler::Async(Rc::new(move |req, info| Box::pin(func(req, info)))),
326 vec![Method::Options],
327 );
328 self
329 }
330
331 pub fn on_async<T>(
334 mut self,
335 pattern: &str,
336 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
337 ) -> Self
338 where
339 T: Future<Output = Result<Response>> + 'a,
340 {
341 self.add_handler(
342 pattern,
343 Handler::Async(Rc::new(move |req, route| Box::pin(func(req, route)))),
344 Method::all(),
345 );
346 self
347 }
348
349 pub fn or_else_any_method_async<T>(
352 mut self,
353 pattern: &str,
354 func: impl Fn(Request, RouteContext<D>) -> T + 'a,
355 ) -> Self
356 where
357 T: Future<Output = Result<Response>> + 'a,
358 {
359 self.or_else_any_method
360 .insert(
361 pattern,
362 Handler::Async(Rc::new(move |req, route| Box::pin(func(req, route)))),
363 )
364 .unwrap_or_else(|e| panic!("failed to register route for {} pattern: {}", pattern, e));
365 self
366 }
367
368 fn add_handler(&mut self, pattern: &str, func: Handler<'a, D>, methods: Vec<Method>) {
369 for method in methods {
370 self.handlers
371 .entry(method.clone())
372 .or_default()
373 .insert(pattern, func.clone())
374 .unwrap_or_else(|e| {
375 panic!(
376 "failed to register {:?} route for {} pattern: {}",
377 method, pattern, e
378 )
379 });
380 }
381 }
382
383 pub async fn run(self, req: Request, env: Env) -> Result<Response> {
385 let (handlers, data, or_else_any_method_handler) = self.split();
386
387 if let Some(handlers) = handlers.get(&req.method()) {
388 if let Ok(Match { value, params }) = handlers.at(&req.path()) {
389 let route_info = RouteContext {
390 data,
391 env,
392 params: params.into(),
393 };
394 return match value {
395 Handler::Sync(func) => (func)(req, route_info),
396 Handler::Async(func) => (func)(req, route_info).await,
397 };
398 }
399 }
400
401 for method in Method::all() {
402 if method == Method::Head || method == Method::Options || method == Method::Trace {
403 continue;
404 }
405 if let Some(handlers) = handlers.get(&method) {
406 if let Ok(Match { .. }) = handlers.at(&req.path()) {
407 return Response::error("Method Not Allowed", 405);
408 }
409 }
410 }
411
412 if let Ok(Match { value, params }) = or_else_any_method_handler.at(&req.path()) {
413 let route_info = RouteContext {
414 data,
415 env,
416 params: params.into(),
417 };
418 return match value {
419 Handler::Sync(func) => (func)(req, route_info),
420 Handler::Async(func) => (func)(req, route_info).await,
421 };
422 }
423
424 Response::error("Not Found", 404)
425 }
426}
427
428type NodeWithHandlers<'a, D> = MatchItRouter<Handler<'a, D>>;
429
430impl<'a, D: 'a> Router<'a, D> {
431 fn split(
432 self,
433 ) -> (
434 HashMap<Method, NodeWithHandlers<'a, D>>,
435 D,
436 NodeWithHandlers<'a, D>,
437 ) {
438 (self.handlers, self.data, self.or_else_any_method)
439 }
440}
441
442impl From<matchit::Params<'_, '_>> for RouteParams {
443 fn from(p: matchit::Params) -> Self {
444 let mut route_params = RouteParams(HashMap::new());
445 for (ident, value) in p.iter() {
446 route_params.0.insert(ident.into(), value.into());
447 }
448
449 route_params
450 }
451}