1use std::fmt::Debug;
2use std::io;
3use std::path::Path;
4use std::sync::Arc;
5use http::Method;
6use crate::errors::HttpResult;
7use super::{Endpoint, Middleware, MiddlewareEndpoint, Request, Response, Router, ServeDir, ServeFile};
8
9#[allow(missing_debug_implementations)]
10pub struct Route<'a, Req: Request, Resp: Response> {
11 router: &'a mut Router<Req, Resp>,
12 path: String,
13 middleware: Vec<Arc<dyn Middleware<Req, Resp>>>,
14 prefix: bool,
15}
16
17impl<'a, Req: Request, Resp: Response> Route<'a, Req, Resp> {
18 pub(crate) fn new(router: &'a mut Router<Req, Resp>, path: String) -> Route<'a, Req, Resp> {
19 Route {
20 router,
21 path,
22 middleware: Vec::new(),
23 prefix: false,
24 }
25 }
26
27 pub fn at<'b>(&'b mut self, path: &str) -> Route<'b, Req, Resp> {
29 let mut p = self.path.clone();
30
31 if !p.ends_with('/') && !path.starts_with('/') {
32 p.push('/');
33 }
34
35 if path != "/" {
36 p.push_str(path);
37 }
38
39 Route {
40 router: &mut self.router,
41 path: p,
42 middleware: self.middleware.clone(),
43 prefix: false,
44 }
45 }
46
47 #[must_use]
48 pub fn path(&self) -> &str {
49 &self.path
50 }
51
52 pub fn with<M>(&mut self, middleware: M) -> &mut Self
53 where
54 M: Middleware<Req, Resp>,
55 {
56 log::trace!(
57 "Adding middleware {} to route {:?}",
58 middleware.name(),
59 self.path
60 );
61 self.middleware.push(Arc::new(middleware));
62 self
63 }
64
65 pub fn reset_middleware(&mut self) -> &mut Self {
66 self.middleware.clear();
67 self
68 }
69
70 pub fn serve_dir(&mut self, dir: impl AsRef<Path>) -> io::Result<()> {
71 let dir = dir.as_ref().to_owned().canonicalize()?;
73 let prefix = self.path().to_string();
74 self.at("*").get(ServeDir::new(prefix, dir));
75 Ok(())
76 }
77
78 pub fn serve_file(&mut self, file: impl AsRef<Path>) -> io::Result<()> {
79 self.get(ServeFile::init(file)?);
80 Ok(())
81 }
82
83 pub fn method(&mut self, method: Method, ep: impl Endpoint<Req, Resp>) -> &mut Self {
84 if self.prefix {
85 let ep = StripPrefixEndpoint::new(ep);
86
87 self.router.add(
88 &self.path,
89 method.clone(),
90 MiddlewareEndpoint::wrap_with_middleware(ep.clone(), &self.middleware),
91 );
92 let wildcard = self.at("*--tide-path-rest");
93 wildcard.router.add(
94 &wildcard.path,
95 method,
96 MiddlewareEndpoint::wrap_with_middleware(ep, &wildcard.middleware),
97 );
98 } else {
99 self.router.add(
100 &self.path,
101 method,
102 MiddlewareEndpoint::wrap_with_middleware(ep, &self.middleware),
103 );
104 }
105 self
106 }
107
108 pub fn all(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
109 if self.prefix {
110 let ep = StripPrefixEndpoint::new(ep);
111
112 self.router.add_all(
113 &self.path,
114 MiddlewareEndpoint::wrap_with_middleware(ep.clone(), &self.middleware),
115 );
116 let wildcard = self.at("*--tide-path-rest");
117 wildcard.router.add_all(
118 &wildcard.path,
119 MiddlewareEndpoint::wrap_with_middleware(ep, &wildcard.middleware),
120 );
121 } else {
122 self.router.add_all(
123 &self.path,
124 MiddlewareEndpoint::wrap_with_middleware(ep, &self.middleware),
125 );
126 }
127 self
128 }
129
130 pub fn get(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
132 self.method(Method::GET, ep);
133 self
134 }
135
136 pub fn head(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
138 self.method(Method::HEAD, ep);
139 self
140 }
141
142 pub fn put(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
144 self.method(Method::PUT, ep);
145 self
146 }
147
148 pub fn post(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
150 self.method(Method::POST, ep);
151 self
152 }
153
154 pub fn delete(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
156 self.method(Method::DELETE, ep);
157 self
158 }
159
160 pub fn options(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
162 self.method(Method::OPTIONS, ep);
163 self
164 }
165
166 pub fn connect(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
168 self.method(Method::CONNECT, ep);
169 self
170 }
171
172 pub fn patch(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
174 self.method(Method::PATCH, ep);
175 self
176 }
177
178 pub fn trace(&mut self, ep: impl Endpoint<Req, Resp>) -> &mut Self {
180 self.method(Method::TRACE, ep);
181 self
182 }
183}
184
185#[derive(Debug)]
186struct StripPrefixEndpoint<E>(std::sync::Arc<E>);
187
188impl<E> StripPrefixEndpoint<E> {
189 fn new(ep: E) -> Self {
190 Self(std::sync::Arc::new(ep))
191 }
192}
193
194impl<E> Clone for StripPrefixEndpoint<E> {
195 fn clone(&self) -> Self {
196 Self(self.0.clone())
197 }
198}
199
200#[async_trait::async_trait]
201impl<Req: Request, Resp: Response, E> Endpoint<Req, Resp> for StripPrefixEndpoint<E>
202where
203 E: Endpoint<Req, Resp>,
204{
205 async fn call(&self, req: Req) -> HttpResult<Resp> {
206 self.0
207 .call(req)
208 .await
209 }
210}