playwright_core/protocol/
route.rs1use crate::channel_owner::{ChannelOwner, ChannelOwnerImpl, ParentOrConnection};
9use crate::error::Result;
10use crate::protocol::Request;
11use serde_json::{json, Value};
12use std::any::Any;
13use std::sync::Arc;
14
15#[derive(Clone)]
21pub struct Route {
22 base: ChannelOwnerImpl,
23}
24
25impl Route {
26 pub fn new(
31 parent: Arc<dyn ChannelOwner>,
32 type_name: String,
33 guid: Arc<str>,
34 initializer: Value,
35 ) -> Result<Self> {
36 let base = ChannelOwnerImpl::new(
37 ParentOrConnection::Parent(parent.clone()),
38 type_name,
39 guid,
40 initializer,
41 );
42
43 Ok(Self { base })
44 }
45
46 pub fn request(&self) -> Request {
50 if let Some(parent) = self.parent() {
53 if let Some(request) = parent.as_any().downcast_ref::<Request>() {
54 return request.clone();
55 }
56 }
57
58 let request_data = self
61 .initializer()
62 .get("request")
63 .cloned()
64 .unwrap_or_else(|| {
65 serde_json::json!({
66 "url": "",
67 "method": "GET"
68 })
69 });
70
71 let parent = self
72 .parent()
73 .unwrap_or_else(|| Arc::new(self.clone()) as Arc<dyn ChannelOwner>);
74
75 let request_guid = request_data
76 .get("guid")
77 .and_then(|v| v.as_str())
78 .unwrap_or("request-stub");
79
80 Request::new(
81 parent,
82 "Request".to_string(),
83 Arc::from(request_guid),
84 request_data,
85 )
86 .unwrap()
87 }
88
89 pub async fn abort(&self, error_code: Option<&str>) -> Result<()> {
108 let params = json!({
109 "errorCode": error_code.unwrap_or("failed")
110 });
111
112 self.channel()
113 .send::<_, serde_json::Value>("abort", params)
114 .await
115 .map(|_| ())
116 }
117
118 pub async fn continue_(&self, overrides: Option<ContinueOptions>) -> Result<()> {
126 let mut params = json!({
127 "isFallback": false
128 });
129
130 if let Some(opts) = overrides {
132 if let Some(headers) = opts.headers {
134 let headers_array: Vec<serde_json::Value> = headers
135 .into_iter()
136 .map(|(name, value)| json!({"name": name, "value": value}))
137 .collect();
138 params["headers"] = json!(headers_array);
139 }
140
141 if let Some(method) = opts.method {
143 params["method"] = json!(method);
144 }
145
146 if let Some(post_data) = opts.post_data {
148 params["postData"] = json!(post_data);
149 } else if let Some(post_data_bytes) = opts.post_data_bytes {
150 use base64::Engine;
151 let encoded = base64::engine::general_purpose::STANDARD.encode(&post_data_bytes);
152 params["postData"] = json!(encoded);
153 }
154
155 if let Some(url) = opts.url {
157 params["url"] = json!(url);
158 }
159 }
160
161 self.channel()
162 .send::<_, serde_json::Value>("continue", params)
163 .await
164 .map(|_| ())
165 }
166
167 pub async fn fulfill(&self, options: Option<FulfillOptions>) -> Result<()> {
196 let opts = options.unwrap_or_default();
197
198 let mut response = json!({
200 "status": opts.status.unwrap_or(200),
201 "headers": []
202 });
203
204 let mut headers_map = opts.headers.unwrap_or_default();
206
207 let body_bytes = opts.body.as_ref();
209 if let Some(body) = body_bytes {
210 let content_length = body.len().to_string();
211 headers_map.insert("content-length".to_string(), content_length);
212 }
213
214 if let Some(ref ct) = opts.content_type {
216 headers_map.insert("content-type".to_string(), ct.clone());
217 }
218
219 let headers_array: Vec<Value> = headers_map
221 .into_iter()
222 .map(|(name, value)| json!({"name": name, "value": value}))
223 .collect();
224 response["headers"] = json!(headers_array);
225
226 if let Some(body) = body_bytes {
228 if let Ok(body_str) = std::str::from_utf8(body) {
230 response["body"] = json!(body_str);
231 } else {
232 use base64::Engine;
233 let encoded = base64::engine::general_purpose::STANDARD.encode(body);
234 response["body"] = json!(encoded);
235 response["isBase64"] = json!(true);
236 }
237 }
238
239 let params = json!({
240 "response": response
241 });
242
243 self.channel()
244 .send::<_, serde_json::Value>("fulfill", params)
245 .await
246 .map(|_| ())
247 }
248}
249
250#[derive(Debug, Clone, Default)]
256pub struct ContinueOptions {
257 pub headers: Option<std::collections::HashMap<String, String>>,
259 pub method: Option<String>,
261 pub post_data: Option<String>,
263 pub post_data_bytes: Option<Vec<u8>>,
265 pub url: Option<String>,
267}
268
269impl ContinueOptions {
270 pub fn builder() -> ContinueOptionsBuilder {
272 ContinueOptionsBuilder::default()
273 }
274}
275
276#[derive(Debug, Clone, Default)]
278pub struct ContinueOptionsBuilder {
279 headers: Option<std::collections::HashMap<String, String>>,
280 method: Option<String>,
281 post_data: Option<String>,
282 post_data_bytes: Option<Vec<u8>>,
283 url: Option<String>,
284}
285
286impl ContinueOptionsBuilder {
287 pub fn headers(mut self, headers: std::collections::HashMap<String, String>) -> Self {
289 self.headers = Some(headers);
290 self
291 }
292
293 pub fn method(mut self, method: String) -> Self {
295 self.method = Some(method);
296 self
297 }
298
299 pub fn post_data(mut self, post_data: String) -> Self {
301 self.post_data = Some(post_data);
302 self.post_data_bytes = None; self
304 }
305
306 pub fn post_data_bytes(mut self, post_data_bytes: Vec<u8>) -> Self {
308 self.post_data_bytes = Some(post_data_bytes);
309 self.post_data = None; self
311 }
312
313 pub fn url(mut self, url: String) -> Self {
315 self.url = Some(url);
316 self
317 }
318
319 pub fn build(self) -> ContinueOptions {
321 ContinueOptions {
322 headers: self.headers,
323 method: self.method,
324 post_data: self.post_data,
325 post_data_bytes: self.post_data_bytes,
326 url: self.url,
327 }
328 }
329}
330
331#[derive(Debug, Clone, Default)]
335pub struct FulfillOptions {
336 pub status: Option<u16>,
338 pub headers: Option<std::collections::HashMap<String, String>>,
340 pub body: Option<Vec<u8>>,
342 pub content_type: Option<String>,
344}
345
346impl FulfillOptions {
347 pub fn builder() -> FulfillOptionsBuilder {
349 FulfillOptionsBuilder::default()
350 }
351}
352
353#[derive(Debug, Clone, Default)]
355pub struct FulfillOptionsBuilder {
356 status: Option<u16>,
357 headers: Option<std::collections::HashMap<String, String>>,
358 body: Option<Vec<u8>>,
359 content_type: Option<String>,
360}
361
362impl FulfillOptionsBuilder {
363 pub fn status(mut self, status: u16) -> Self {
365 self.status = Some(status);
366 self
367 }
368
369 pub fn headers(mut self, headers: std::collections::HashMap<String, String>) -> Self {
371 self.headers = Some(headers);
372 self
373 }
374
375 pub fn body(mut self, body: Vec<u8>) -> Self {
377 self.body = Some(body);
378 self
379 }
380
381 pub fn body_string(mut self, body: impl Into<String>) -> Self {
383 self.body = Some(body.into().into_bytes());
384 self
385 }
386
387 pub fn json(mut self, value: &impl serde::Serialize) -> Result<Self> {
389 let json_str = serde_json::to_string(value).map_err(|e| {
390 crate::error::Error::ProtocolError(format!("JSON serialization failed: {}", e))
391 })?;
392 self.body = Some(json_str.into_bytes());
393 self.content_type = Some("application/json".to_string());
394 Ok(self)
395 }
396
397 pub fn content_type(mut self, content_type: impl Into<String>) -> Self {
399 self.content_type = Some(content_type.into());
400 self
401 }
402
403 pub fn build(self) -> FulfillOptions {
405 FulfillOptions {
406 status: self.status,
407 headers: self.headers,
408 body: self.body,
409 content_type: self.content_type,
410 }
411 }
412}
413
414impl ChannelOwner for Route {
415 fn guid(&self) -> &str {
416 self.base.guid()
417 }
418
419 fn type_name(&self) -> &str {
420 self.base.type_name()
421 }
422
423 fn parent(&self) -> Option<Arc<dyn ChannelOwner>> {
424 self.base.parent()
425 }
426
427 fn connection(&self) -> Arc<dyn crate::connection::ConnectionLike> {
428 self.base.connection()
429 }
430
431 fn initializer(&self) -> &Value {
432 self.base.initializer()
433 }
434
435 fn channel(&self) -> &crate::channel::Channel {
436 self.base.channel()
437 }
438
439 fn dispose(&self, reason: crate::channel_owner::DisposeReason) {
440 self.base.dispose(reason)
441 }
442
443 fn adopt(&self, child: Arc<dyn ChannelOwner>) {
444 self.base.adopt(child)
445 }
446
447 fn add_child(&self, guid: Arc<str>, child: Arc<dyn ChannelOwner>) {
448 self.base.add_child(guid, child)
449 }
450
451 fn remove_child(&self, guid: &str) {
452 self.base.remove_child(guid)
453 }
454
455 fn on_event(&self, _method: &str, _params: Value) {
456 }
458
459 fn was_collected(&self) -> bool {
460 self.base.was_collected()
461 }
462
463 fn as_any(&self) -> &dyn Any {
464 self
465 }
466}
467
468impl std::fmt::Debug for Route {
469 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470 f.debug_struct("Route")
471 .field("guid", &self.guid())
472 .field("request", &self.request().guid())
473 .finish()
474 }
475}