playwright/imp/
request.rs1use crate::imp::{
2 core::*,
3 frame::Frame,
4 prelude::*,
5 response::Response,
6 utils::{Header, ResponseTiming}
7};
8
9#[derive(Debug)]
10pub(crate) struct Request {
11 channel: ChannelOwner,
12 url: String,
13 resource_type: String,
14 method: String,
15 is_navigation_request: bool,
16 post_data: Option<String>,
17 frame: Weak<Frame>,
18 headers: HashMap<String, String>,
19 redirected_from: Option<Weak<Request>>,
20 var: Mutex<Variable>
21}
22
23#[derive(Debug, Default)]
24pub(crate) struct Variable {
25 redirected_to: Option<Weak<Request>>,
26 failure: Option<String>,
27 timing: Option<ResponseTiming>,
28 response_end: Option<f64>
29}
30
31impl Request {
32 pub(crate) fn try_new(ctx: &Context, channel: ChannelOwner) -> Result<Arc<Self>, Error> {
33 let Initializer {
34 url,
35 resource_type,
36 method,
37 frame,
38 is_navigation_request,
39 post_data,
40 headers,
41 redirected_from
42 } = serde_json::from_value(channel.initializer.clone())?;
43 let headers: HashMap<_, _> = headers
44 .into_iter()
45 .map(Into::<(_, _)>::into)
46 .map(|(mut k, v)| {
47 k.make_ascii_lowercase();
48 (k, v)
49 })
50 .collect();
51 let frame = get_object!(ctx, &frame.guid, Frame)?;
52 let redirected_from =
53 match redirected_from.map(|OnlyGuid { guid }| get_object!(ctx, &guid, Request)) {
54 None => None,
55 Some(Ok(x)) => Some(x),
56 Some(Err(e)) => return Err(e)
57 };
58 let var = Mutex::new(Variable::default());
59 let arc = Arc::new(Self {
60 channel,
61 url,
62 resource_type,
63 method,
64 is_navigation_request,
65 post_data,
66 frame,
67 headers,
68 redirected_from,
69 var
70 });
71 if let Some(from) = arc.redirected_from.as_ref().and_then(|w| w.upgrade()) {
72 let this = Arc::downgrade(&arc);
73 from.set_redirected_to(this);
74 }
75 Ok(arc)
76 }
77
78 pub(crate) fn url(&self) -> &str { &self.url }
79
80 pub(crate) fn resource_type(&self) -> &str { &self.resource_type }
81
82 pub(crate) fn method(&self) -> &str { &self.method }
83
84 pub(crate) fn is_navigation_request(&self) -> bool { self.is_navigation_request }
85
86 pub(crate) fn frame(&self) -> Weak<Frame> { self.frame.clone() }
87
88 pub(crate) fn post_data(&self) -> Option<Vec<u8>> {
89 base64::decode(self.post_data.as_ref()?).ok()
90 }
91
92 pub(crate) fn post_data_as_string(&self) -> Option<String> {
93 let bytes = self.post_data()?;
94 let s = String::from_utf8(bytes).ok()?;
95 Some(s)
96 }
97
98 pub(crate) fn headers(&self) -> &HashMap<String, String> { &self.headers }
99
100 pub(crate) fn redirected_from(&self) -> Option<Weak<Request>> { self.redirected_from.clone() }
101
102 pub(crate) async fn response(&self) -> ArcResult<Option<Weak<Response>>> {
103 let v = send_message!(self, "response", Map::new());
104 let guid = match as_only_guid(&v) {
105 Some(g) => g,
106 None => return Ok(None)
107 };
108 let r = get_object!(self.context()?.lock().unwrap(), guid, Response)?;
109 Ok(Some(r))
110 }
111}
112
113impl Request {
114 pub(crate) fn timing(&self) -> Option<ResponseTiming> {
115 self.var.lock().unwrap().timing.clone()
116 }
117
118 pub(crate) fn response_end(&self) -> Option<f64> { self.var.lock().unwrap().response_end }
119
120 pub(crate) fn failure(&self) -> Option<String> { self.var.lock().unwrap().failure.clone() }
121
122 pub(crate) fn redirected_to(&self) -> Option<Weak<Request>> {
123 self.var.lock().unwrap().redirected_to.clone()
124 }
125
126 fn set_redirected_to(&self, to: Weak<Request>) {
127 let var = &mut self.var.lock().unwrap();
128 var.redirected_to = Some(to);
129 }
130
131 pub(crate) fn set_response_timing(&self, timing: ResponseTiming) {
132 let var = &mut self.var.lock().unwrap();
133 var.timing = Some(timing);
134 }
135
136 pub(crate) fn set_response_end(&self, response_end: f64) {
137 let var = &mut self.var.lock().unwrap();
138 var.response_end = Some(response_end);
139 }
140
141 pub(crate) fn set_failure(&self, failure: Option<String>) {
142 let var = &mut self.var.lock().unwrap();
143 var.failure = failure;
144 }
145}
146
147impl Request {
149 }
153
154impl RemoteObject for Request {
155 fn channel(&self) -> &ChannelOwner { &self.channel }
156 fn channel_mut(&mut self) -> &mut ChannelOwner { &mut self.channel }
157}
158
159#[derive(Debug, Deserialize)]
160#[serde(rename_all = "camelCase")]
161struct Initializer {
162 url: String,
163 resource_type: String,
164 method: String,
165 frame: OnlyGuid,
166 is_navigation_request: bool,
167 post_data: Option<String>,
169 headers: Vec<Header>,
170 redirected_from: Option<OnlyGuid>
171}