1use serde::{Deserialize, Serialize};
8
9use super::network::{Request, ResourceType};
10
11pub type RequestId = String;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct HeaderEntry {
17 pub name: String,
19 pub value: String,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
25pub enum RequestStage {
26 #[default]
28 Request,
29 Response,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, Default)]
35#[serde(rename_all = "camelCase")]
36pub struct RequestPattern {
37 #[serde(skip_serializing_if = "Option::is_none")]
40 pub url_pattern: Option<String>,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub resource_type: Option<ResourceType>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub request_stage: Option<RequestStage>,
49}
50
51impl RequestPattern {
52 pub fn all() -> Self {
54 Self::default()
55 }
56
57 pub fn url(pattern: impl Into<String>) -> Self {
59 Self {
60 url_pattern: Some(pattern.into()),
61 ..Default::default()
62 }
63 }
64
65 #[must_use]
67 pub fn with_resource_type(mut self, resource_type: ResourceType) -> Self {
68 self.resource_type = Some(resource_type);
69 self
70 }
71
72 #[must_use]
74 pub fn with_stage(mut self, stage: RequestStage) -> Self {
75 self.request_stage = Some(stage);
76 self
77 }
78}
79
80#[derive(Debug, Clone, Serialize, Default)]
86#[serde(rename_all = "camelCase")]
87pub struct EnableParams {
88 #[serde(skip_serializing_if = "Option::is_none")]
92 pub patterns: Option<Vec<RequestPattern>>,
93
94 #[serde(skip_serializing_if = "Option::is_none")]
97 pub handle_auth_requests: Option<bool>,
98}
99
100#[derive(Debug, Clone, Serialize, Default)]
102pub struct DisableParams {}
103
104#[derive(Debug, Clone, Serialize, Default)]
106#[serde(rename_all = "camelCase")]
107pub struct ContinueRequestParams {
108 pub request_id: RequestId,
110
111 #[serde(skip_serializing_if = "Option::is_none")]
113 pub url: Option<String>,
114
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub method: Option<String>,
118
119 #[serde(skip_serializing_if = "Option::is_none")]
122 pub post_data: Option<String>,
123
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub headers: Option<Vec<HeaderEntry>>,
127
128 #[serde(skip_serializing_if = "Option::is_none")]
130 pub intercept_response: Option<bool>,
131}
132
133#[derive(Debug, Clone, Serialize)]
135#[serde(rename_all = "camelCase")]
136pub struct FulfillRequestParams {
137 pub request_id: RequestId,
139
140 pub response_code: i32,
142
143 #[serde(skip_serializing_if = "Option::is_none")]
145 pub response_headers: Option<Vec<HeaderEntry>>,
146
147 #[serde(skip_serializing_if = "Option::is_none")]
150 pub binary_response_headers: Option<String>,
151
152 #[serde(skip_serializing_if = "Option::is_none")]
157 pub body: Option<String>,
158
159 #[serde(skip_serializing_if = "Option::is_none")]
162 pub response_phrase: Option<String>,
163}
164
165#[derive(Debug, Clone, Serialize)]
167#[serde(rename_all = "camelCase")]
168pub struct FailRequestParams {
169 pub request_id: RequestId,
171
172 pub error_reason: ErrorReason,
174}
175
176#[derive(Debug, Clone, Serialize)]
178#[serde(rename_all = "camelCase")]
179pub struct GetResponseBodyParams {
180 pub request_id: RequestId,
182}
183
184#[derive(Debug, Clone, Deserialize)]
186#[serde(rename_all = "camelCase")]
187pub struct GetResponseBodyResult {
188 pub body: String,
190
191 pub base64_encoded: bool,
193}
194
195#[derive(Debug, Clone, Serialize)]
197#[serde(rename_all = "camelCase")]
198pub struct ContinueWithAuthParams {
199 pub request_id: RequestId,
201
202 pub auth_challenge_response: AuthChallengeResponse,
204}
205
206#[derive(Debug, Clone, Serialize, Default)]
208#[serde(rename_all = "camelCase")]
209pub struct ContinueResponseParams {
210 pub request_id: RequestId,
212
213 #[serde(skip_serializing_if = "Option::is_none")]
215 pub response_code: Option<i32>,
216
217 #[serde(skip_serializing_if = "Option::is_none")]
219 pub response_phrase: Option<String>,
220
221 #[serde(skip_serializing_if = "Option::is_none")]
223 pub response_headers: Option<Vec<HeaderEntry>>,
224
225 #[serde(skip_serializing_if = "Option::is_none")]
227 pub binary_response_headers: Option<String>,
228}
229
230#[derive(Debug, Clone, Deserialize)]
240#[serde(rename_all = "camelCase")]
241pub struct RequestPausedEvent {
242 pub request_id: RequestId,
244
245 pub request: Request,
247
248 pub frame_id: String,
250
251 pub resource_type: ResourceType,
253
254 #[serde(skip_serializing_if = "Option::is_none")]
256 pub response_error_reason: Option<ErrorReason>,
257
258 #[serde(skip_serializing_if = "Option::is_none")]
260 pub response_status_code: Option<i32>,
261
262 #[serde(skip_serializing_if = "Option::is_none")]
264 pub response_status_text: Option<String>,
265
266 #[serde(skip_serializing_if = "Option::is_none")]
268 pub response_headers: Option<Vec<HeaderEntry>>,
269
270 #[serde(skip_serializing_if = "Option::is_none")]
273 pub network_id: Option<String>,
274
275 #[serde(skip_serializing_if = "Option::is_none")]
278 pub redirected_request_id: Option<RequestId>,
279}
280
281impl RequestPausedEvent {
282 pub fn is_response_stage(&self) -> bool {
284 self.response_error_reason.is_some() || self.response_status_code.is_some()
285 }
286
287 pub fn is_request_stage(&self) -> bool {
289 !self.is_response_stage()
290 }
291
292 pub fn is_redirect(&self) -> bool {
294 if let Some(code) = self.response_status_code {
295 matches!(code, 301 | 302 | 303 | 307 | 308)
296 && self.response_headers.as_ref().is_some_and(|headers| {
297 headers
298 .iter()
299 .any(|h| h.name.eq_ignore_ascii_case("location"))
300 })
301 } else {
302 false
303 }
304 }
305}
306
307#[derive(Debug, Clone, Deserialize)]
312#[serde(rename_all = "camelCase")]
313pub struct AuthRequiredEvent {
314 pub request_id: RequestId,
316
317 pub request: Request,
319
320 pub frame_id: String,
322
323 pub resource_type: ResourceType,
325
326 pub auth_challenge: AuthChallenge,
328}
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
336pub enum ErrorReason {
337 #[default]
339 Failed,
340 Aborted,
342 TimedOut,
344 AccessDenied,
346 ConnectionClosed,
348 ConnectionReset,
350 ConnectionRefused,
352 ConnectionAborted,
354 ConnectionFailed,
356 NameNotResolved,
358 InternetDisconnected,
360 AddressUnreachable,
362 BlockedByClient,
364 BlockedByResponse,
366}
367
368impl ErrorReason {
369 pub fn as_str(&self) -> &'static str {
371 match self {
372 Self::Failed => "Failed",
373 Self::Aborted => "Aborted",
374 Self::TimedOut => "TimedOut",
375 Self::AccessDenied => "AccessDenied",
376 Self::ConnectionClosed => "ConnectionClosed",
377 Self::ConnectionReset => "ConnectionReset",
378 Self::ConnectionRefused => "ConnectionRefused",
379 Self::ConnectionAborted => "ConnectionAborted",
380 Self::ConnectionFailed => "ConnectionFailed",
381 Self::NameNotResolved => "NameNotResolved",
382 Self::InternetDisconnected => "InternetDisconnected",
383 Self::AddressUnreachable => "AddressUnreachable",
384 Self::BlockedByClient => "BlockedByClient",
385 Self::BlockedByResponse => "BlockedByResponse",
386 }
387 }
388}
389
390#[derive(Debug, Clone, Deserialize)]
392#[serde(rename_all = "camelCase")]
393pub struct AuthChallenge {
394 pub source: AuthChallengeSource,
396
397 pub origin: String,
399
400 pub scheme: String,
402
403 pub realm: String,
405}
406
407#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
409pub enum AuthChallengeSource {
410 Server,
412 Proxy,
414}
415
416#[derive(Debug, Clone, Serialize)]
418#[serde(rename_all = "camelCase")]
419pub struct AuthChallengeResponse {
420 pub response: AuthChallengeResponseType,
422
423 #[serde(skip_serializing_if = "Option::is_none")]
426 pub username: Option<String>,
427
428 #[serde(skip_serializing_if = "Option::is_none")]
431 pub password: Option<String>,
432}
433
434#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
436pub enum AuthChallengeResponseType {
437 Default,
439 CancelAuth,
441 ProvideCredentials,
443}
444
445impl AuthChallengeResponse {
446 pub fn default_response() -> Self {
448 Self {
449 response: AuthChallengeResponseType::Default,
450 username: None,
451 password: None,
452 }
453 }
454
455 pub fn cancel() -> Self {
457 Self {
458 response: AuthChallengeResponseType::CancelAuth,
459 username: None,
460 password: None,
461 }
462 }
463
464 pub fn provide_credentials(username: impl Into<String>, password: impl Into<String>) -> Self {
466 Self {
467 response: AuthChallengeResponseType::ProvideCredentials,
468 username: Some(username.into()),
469 password: Some(password.into()),
470 }
471 }
472}
473
474