viewpoint_core/network/route/
mod.rs1use std::future::Future;
4use std::pin::Pin;
5use std::sync::Arc;
6use std::time::Duration;
7
8use tokio::sync::Mutex;
9use viewpoint_cdp::protocol::fetch::{
10 ContinueRequestParams, ErrorReason, FailRequestParams, FulfillRequestParams,
11 GetResponseBodyParams, GetResponseBodyResult, HeaderEntry,
12};
13use viewpoint_cdp::CdpConnection;
14
15use super::request::Request;
16use super::route_builders::{ContinueBuilder, FulfillBuilder};
17use super::route_fetch::{FetchBuilder, FetchedResponse};
18use super::types::AbortError;
19use crate::error::NetworkError;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum RouteAction {
27 Handled,
29 Fallback,
31}
32
33pub type RouteHandler = Box<
35 dyn Fn(Route) -> Pin<Box<dyn Future<Output = Result<(), NetworkError>> + Send>>
36 + Send
37 + Sync,
38>;
39
40#[derive(Debug, Clone)]
46pub struct Route {
47 request: Request,
49 request_id: String,
51 connection: Arc<CdpConnection>,
53 session_id: String,
55 handled: Arc<Mutex<bool>>,
57 response_status: Option<u16>,
59 response_headers: Option<Vec<HeaderEntry>>,
61}
62
63impl Route {
64 pub(crate) fn new(
66 request: Request,
67 request_id: String,
68 connection: Arc<CdpConnection>,
69 session_id: String,
70 response_status: Option<u16>,
71 response_headers: Option<Vec<HeaderEntry>>,
72 ) -> Self {
73 Self {
74 request,
75 request_id,
76 connection,
77 session_id,
78 handled: Arc::new(Mutex::new(false)),
79 response_status,
80 response_headers,
81 }
82 }
83
84 pub fn request(&self) -> &Request {
86 &self.request
87 }
88
89 pub(super) fn request_id(&self) -> &str {
91 &self.request_id
92 }
93
94 pub(super) fn connection(&self) -> &Arc<CdpConnection> {
96 &self.connection
97 }
98
99 pub(super) fn session_id(&self) -> &str {
101 &self.session_id
102 }
103
104 pub async fn is_handled(&self) -> bool {
106 *self.handled.lock().await
107 }
108
109 pub fn is_response_stage(&self) -> bool {
111 self.response_status.is_some()
112 }
113
114 pub fn response_status(&self) -> Option<u16> {
116 self.response_status
117 }
118
119 pub fn response_headers(&self) -> Option<&[HeaderEntry]> {
121 self.response_headers.as_deref()
122 }
123
124 pub async fn response_body(&self) -> Result<Option<Vec<u8>>, NetworkError> {
130 if !self.is_response_stage() {
131 return Ok(None);
132 }
133 self.get_response_body(&self.request_id).await
134 }
135
136 pub fn fulfill(&self) -> FulfillBuilder<'_> {
149 FulfillBuilder::new(self)
150 }
151
152 pub fn continue_(&self) -> ContinueBuilder<'_> {
167 ContinueBuilder::new(self)
168 }
169
170 pub async fn abort(&self) -> Result<(), NetworkError> {
176 self.abort_with(AbortError::Failed).await
177 }
178
179 pub async fn abort_with(&self, error: AbortError) -> Result<(), NetworkError> {
185 {
187 let mut handled = self.handled.lock().await;
188 if *handled {
189 return Err(NetworkError::AlreadyHandled);
190 }
191 *handled = true;
192 }
193
194 let error_reason = match error {
195 AbortError::Aborted => ErrorReason::Aborted,
196 AbortError::AccessDenied => ErrorReason::AccessDenied,
197 AbortError::AddressUnreachable => ErrorReason::AddressUnreachable,
198 AbortError::BlockedByClient => ErrorReason::BlockedByClient,
199 AbortError::BlockedByResponse => ErrorReason::BlockedByResponse,
200 AbortError::ConnectionAborted => ErrorReason::ConnectionAborted,
201 AbortError::ConnectionClosed => ErrorReason::ConnectionClosed,
202 AbortError::ConnectionFailed => ErrorReason::ConnectionFailed,
203 AbortError::ConnectionRefused => ErrorReason::ConnectionRefused,
204 AbortError::ConnectionReset => ErrorReason::ConnectionReset,
205 AbortError::InternetDisconnected => ErrorReason::InternetDisconnected,
206 AbortError::NameNotResolved => ErrorReason::NameNotResolved,
207 AbortError::TimedOut => ErrorReason::TimedOut,
208 AbortError::Failed => ErrorReason::Failed,
209 };
210
211 let params = FailRequestParams {
212 request_id: self.request_id.clone(),
213 error_reason,
214 };
215
216 self.connection
217 .send_command::<_, serde_json::Value>("Fetch.failRequest", Some(params), Some(&self.session_id))
218 .await
219 .map_err(NetworkError::from)?;
220
221 Ok(())
222 }
223
224 pub async fn fallback(&self) -> Result<(), NetworkError> {
232 let params = ContinueRequestParams {
235 request_id: self.request_id.clone(),
236 url: None,
237 method: None,
238 post_data: None,
239 headers: None,
240 intercept_response: None,
241 };
242
243 self.connection
244 .send_command::<_, serde_json::Value>("Fetch.continueRequest", Some(params), Some(&self.session_id))
245 .await
246 .map_err(NetworkError::from)?;
247
248 Ok(())
249 }
250
251 pub fn fetch(&self) -> FetchBuilder<'_> {
267 FetchBuilder::new(self)
268 }
269
270 pub async fn fetch_with_timeout(&self, timeout: Duration) -> Result<FetchedResponse<'_>, NetworkError> {
272 self.fetch().timeout(timeout).send().await
273 }
274
275 pub(super) async fn send_fulfill(&self, params: FulfillRequestParams) -> Result<(), NetworkError> {
281 {
283 let mut handled = self.handled.lock().await;
284 if *handled {
285 return Err(NetworkError::AlreadyHandled);
286 }
287 *handled = true;
288 }
289
290 self.connection
291 .send_command::<_, serde_json::Value>("Fetch.fulfillRequest", Some(params), Some(&self.session_id))
292 .await
293 .map_err(NetworkError::from)?;
294
295 Ok(())
296 }
297
298 pub(super) async fn send_continue(&self, params: ContinueRequestParams) -> Result<(), NetworkError> {
300 {
302 let mut handled = self.handled.lock().await;
303 if *handled {
304 return Err(NetworkError::AlreadyHandled);
305 }
306 *handled = true;
307 }
308
309 self.connection
310 .send_command::<_, serde_json::Value>("Fetch.continueRequest", Some(params), Some(&self.session_id))
311 .await
312 .map_err(NetworkError::from)?;
313
314 Ok(())
315 }
316
317 pub(super) async fn get_response_body(&self, request_id: &str) -> Result<Option<Vec<u8>>, NetworkError> {
319 use base64::Engine;
320
321 let result: GetResponseBodyResult = self
322 .connection
323 .send_command(
324 "Fetch.getResponseBody",
325 Some(GetResponseBodyParams {
326 request_id: request_id.to_string(),
327 }),
328 Some(&self.session_id),
329 )
330 .await
331 .map_err(NetworkError::from)?;
332
333 let body = if result.base64_encoded {
334 base64::engine::general_purpose::STANDARD
335 .decode(&result.body)
336 .ok()
337 } else {
338 Some(result.body.into_bytes())
339 };
340
341 Ok(body)
342 }
343}
344
345#[cfg(test)]
346mod tests;