playwright/imp/
request.rs

1use 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
147// mutable
148impl Request {
149    // redirected_to
150    // failure
151    // timing
152}
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    // base64
168    post_data: Option<String>,
169    headers: Vec<Header>,
170    redirected_from: Option<OnlyGuid>
171}