1use crate::{
2 api::{Header, Request},
3 imp::{
4 core::*,
5 prelude::*,
6 route::{ContinueArgs, FulfillArgs, Route as Impl},
7 },
8};
9
10pub struct Route {
13 inner: Weak<Impl>,
14}
15
16impl PartialEq for Route {
17 fn eq(&self, other: &Self) -> bool {
18 let a = self.inner.upgrade();
19 let b = other.inner.upgrade();
20 a.and_then(|a| b.map(|b| (a, b)))
21 .map(|(a, b)| a.guid() == b.guid())
22 .unwrap_or_default()
23 }
24}
25
26impl Route {
27 fn new(inner: Weak<Impl>) -> Self {
28 Self { inner }
29 }
30
31 pub fn request(&self) -> Request {
33 let inner = weak_and_then(&self.inner, |rc| rc.request());
34 Request::new(inner)
35 }
36
37 pub async fn abort(&self, err_code: Option<&str>) -> Result<(), Arc<Error>> {
56 let inner = upgrade(&self.inner)?;
57 inner.abort(err_code).await
58 }
59
60 pub async fn fulfill_builder<'a>(
73 &self,
74 body: &'a str,
75 is_base64: bool,
76 ) -> FulfillBuilder<'a, '_> {
77 FulfillBuilder::new(self.inner.clone(), body, is_base64)
78 }
79
80 pub async fn continue_builder(&self) -> ContinueBuilder<'_, '_, '_> {
94 ContinueBuilder::new(self.inner.clone())
95 }
96}
97
98pub struct FulfillBuilder<'a, 'b> {
99 inner: Weak<Impl>,
100 args: FulfillArgs<'a, 'b>,
101}
102
103impl<'a, 'b> FulfillBuilder<'a, 'b> {
104 pub(crate) fn new(inner: Weak<Impl>, body: &'a str, is_base64: bool) -> Self {
105 let args = FulfillArgs::new(body, is_base64);
106 Self { inner, args }
107 }
108
109 pub async fn fulfill(self) -> Result<(), Arc<Error>> {
110 let Self { inner, args } = self;
111 upgrade(&inner)?.fulfill(args).await
112 }
113
114 pub fn headers<T>(mut self, x: T) -> Self
116 where
117 T: IntoIterator<Item = (String, String)>,
118 {
119 self.args.headers = Some(x.into_iter().map(Header::from).collect());
120 self
121 }
122
123 setter! {
124 content_type: Option<&'b str>,
126 status: Option<i32>
128 }
129
130 pub fn clear_headers(mut self) -> Self {
131 self.args.headers = None;
132 self
133 }
134}
135
136pub struct ContinueBuilder<'a, 'b, 'c> {
137 inner: Weak<Impl>,
138 args: ContinueArgs<'a, 'b, 'c>,
139}
140
141impl<'a, 'b, 'c> ContinueBuilder<'a, 'b, 'c> {
142 pub(crate) fn new(inner: Weak<Impl>) -> Self {
143 let args = ContinueArgs::default();
144 Self { inner, args }
145 }
146
147 pub async fn r#continue(self) -> Result<(), Arc<Error>> {
148 let Self { inner, args } = self;
149 upgrade(&inner)?.r#continue(args).await
150 }
151
152 pub fn headers<T>(mut self, x: T) -> Self
154 where
155 T: IntoIterator<Item = (String, String)>,
156 {
157 self.args.headers = Some(x.into_iter().map(Header::from).collect());
158 self
159 }
160
161 setter! {
162 method: Option<&'b str>,
164 post_data: Option<&'c str>,
166 url: Option<&'a str>
168 }
169
170 pub fn clear_headers(mut self) -> Self {
171 self.args.headers = None;
172 self
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use crate::imp::route::Route as Impl;
180 use std::sync::Weak;
181
182 #[test]
183 fn test_fulfill_builder_headers_and_setters() {
184 let inner: Weak<Impl> = Weak::new();
185 let b = FulfillBuilder::new(inner, "hello", false)
186 .headers(vec![("foo".to_string(), "bar".to_string())])
187 .content_type("text/plain")
188 .status(404);
189
190 assert_eq!(b.args.content_type, Some("text/plain"));
192 assert_eq!(b.args.status, Some(404));
193 assert_eq!(
194 b.args.headers.clone().unwrap(),
195 vec![Header::from(("foo".to_string(), "bar".to_string()))]
196 );
197
198 let b = b.clear_headers();
199 assert!(b.args.headers.is_none());
200 }
201
202 #[test]
203 fn test_continue_builder_headers_and_setters() {
204 let inner: Weak<Impl> = Weak::new();
205 let b = ContinueBuilder::new(inner)
206 .headers(vec![("x".to_string(), "y".to_string())])
207 .method("POST")
208 .post_data("payload")
209 .url("https://example.org");
210
211 assert_eq!(b.args.method, Some("POST"));
212 assert_eq!(b.args.post_data, Some("payload"));
213 assert_eq!(b.args.url, Some("https://example.org"));
214 assert_eq!(
215 b.args.headers.clone().unwrap(),
216 vec![Header::from(("x".to_string(), "y".to_string()))]
217 );
218
219 let b = b.clear_headers();
220 assert!(b.args.headers.is_none());
221 }
222
223 #[tokio::test]
224 async fn test_fulfill_and_continue_fail_on_no_inner() {
225 let inner: Weak<Impl> = Weak::new();
226 let b = FulfillBuilder::new(inner.clone(), "body", false);
227 assert!(b.fulfill().await.is_err());
229
230 let cb = ContinueBuilder::new(inner);
231 assert!(cb.r#continue().await.is_err());
232 }
233
234 #[tokio::test]
235 async fn test_route_abort_and_request_on_no_inner() {
236 let route = Route::new(Weak::new());
237
238 assert!(route.abort(None).await.is_err());
240
241 let request = route.request();
243 assert!(request.url().is_err());
244 }
245}