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<'_> {
153 FulfillBuilder::new(self)
154 }
155
156 pub fn continue_(&self) -> ContinueBuilder<'_> {
178 ContinueBuilder::new(self)
179 }
180
181 pub async fn abort(&self) -> Result<(), NetworkError> {
187 self.abort_with(AbortError::Failed).await
188 }
189
190 pub async fn abort_with(&self, error: AbortError) -> Result<(), NetworkError> {
196 {
198 let mut handled = self.handled.lock().await;
199 if *handled {
200 return Err(NetworkError::AlreadyHandled);
201 }
202 *handled = true;
203 }
204
205 let error_reason = match error {
206 AbortError::Aborted => ErrorReason::Aborted,
207 AbortError::AccessDenied => ErrorReason::AccessDenied,
208 AbortError::AddressUnreachable => ErrorReason::AddressUnreachable,
209 AbortError::BlockedByClient => ErrorReason::BlockedByClient,
210 AbortError::BlockedByResponse => ErrorReason::BlockedByResponse,
211 AbortError::ConnectionAborted => ErrorReason::ConnectionAborted,
212 AbortError::ConnectionClosed => ErrorReason::ConnectionClosed,
213 AbortError::ConnectionFailed => ErrorReason::ConnectionFailed,
214 AbortError::ConnectionRefused => ErrorReason::ConnectionRefused,
215 AbortError::ConnectionReset => ErrorReason::ConnectionReset,
216 AbortError::InternetDisconnected => ErrorReason::InternetDisconnected,
217 AbortError::NameNotResolved => ErrorReason::NameNotResolved,
218 AbortError::TimedOut => ErrorReason::TimedOut,
219 AbortError::Failed => ErrorReason::Failed,
220 };
221
222 let params = FailRequestParams {
223 request_id: self.request_id.clone(),
224 error_reason,
225 };
226
227 self.connection
228 .send_command::<_, serde_json::Value>("Fetch.failRequest", Some(params), Some(&self.session_id))
229 .await
230 .map_err(NetworkError::from)?;
231
232 Ok(())
233 }
234
235 pub async fn fallback(&self) -> Result<(), NetworkError> {
243 let params = ContinueRequestParams {
246 request_id: self.request_id.clone(),
247 url: None,
248 method: None,
249 post_data: None,
250 headers: None,
251 intercept_response: None,
252 };
253
254 self.connection
255 .send_command::<_, serde_json::Value>("Fetch.continueRequest", Some(params), Some(&self.session_id))
256 .await
257 .map_err(NetworkError::from)?;
258
259 Ok(())
260 }
261
262 pub fn fetch(&self) -> FetchBuilder<'_> {
282 FetchBuilder::new(self)
283 }
284
285 pub async fn fetch_with_timeout(&self, timeout: Duration) -> Result<FetchedResponse<'_>, NetworkError> {
287 self.fetch().timeout(timeout).send().await
288 }
289
290 pub(super) async fn send_fulfill(&self, params: FulfillRequestParams) -> Result<(), NetworkError> {
296 {
298 let mut handled = self.handled.lock().await;
299 if *handled {
300 return Err(NetworkError::AlreadyHandled);
301 }
302 *handled = true;
303 }
304
305 self.connection
306 .send_command::<_, serde_json::Value>("Fetch.fulfillRequest", Some(params), Some(&self.session_id))
307 .await
308 .map_err(NetworkError::from)?;
309
310 Ok(())
311 }
312
313 pub(super) async fn send_continue(&self, params: ContinueRequestParams) -> Result<(), NetworkError> {
315 {
317 let mut handled = self.handled.lock().await;
318 if *handled {
319 return Err(NetworkError::AlreadyHandled);
320 }
321 *handled = true;
322 }
323
324 self.connection
325 .send_command::<_, serde_json::Value>("Fetch.continueRequest", Some(params), Some(&self.session_id))
326 .await
327 .map_err(NetworkError::from)?;
328
329 Ok(())
330 }
331
332 pub(super) async fn get_response_body(&self, request_id: &str) -> Result<Option<Vec<u8>>, NetworkError> {
334 use base64::Engine;
335
336 let result: GetResponseBodyResult = self
337 .connection
338 .send_command(
339 "Fetch.getResponseBody",
340 Some(GetResponseBodyParams {
341 request_id: request_id.to_string(),
342 }),
343 Some(&self.session_id),
344 )
345 .await
346 .map_err(NetworkError::from)?;
347
348 let body = if result.base64_encoded {
349 base64::engine::general_purpose::STANDARD
350 .decode(&result.body)
351 .ok()
352 } else {
353 Some(result.body.into_bytes())
354 };
355
356 Ok(body)
357 }
358}
359
360#[cfg(test)]
361mod tests;