playwright_rs/protocol/
response.rs1use crate::error::Result;
8use crate::server::channel_owner::{ChannelOwner, ChannelOwnerImpl, ParentOrConnection};
9use serde_json::Value;
10use std::any::Any;
11use std::sync::Arc;
12
13#[derive(Debug, Clone)]
19pub struct SecurityDetails {
20 pub issuer: Option<String>,
22 pub protocol: Option<String>,
24 pub subject_name: Option<String>,
26 pub valid_from: Option<f64>,
28 pub valid_to: Option<f64>,
30}
31
32#[derive(Debug, Clone)]
36pub struct RemoteAddr {
37 pub ip_address: String,
39 pub port: u16,
41}
42
43#[derive(Debug, Clone)]
47pub struct RequestSizes {
48 pub request_body_size: i64,
50 pub request_headers_size: i64,
53 pub response_body_size: i64,
55 pub response_headers_size: i64,
58}
59
60#[derive(Debug, Clone)]
66pub struct HeaderEntry {
67 pub name: String,
69 pub value: String,
71}
72
73#[derive(Clone)]
80pub struct ResponseObject {
81 base: ChannelOwnerImpl,
82}
83
84impl ResponseObject {
85 pub fn new(
90 parent: Arc<dyn ChannelOwner>,
91 type_name: String,
92 guid: Arc<str>,
93 initializer: Value,
94 ) -> Result<Self> {
95 let base = ChannelOwnerImpl::new(
96 ParentOrConnection::Parent(parent),
97 type_name,
98 guid,
99 initializer,
100 );
101
102 Ok(Self { base })
103 }
104
105 pub fn status(&self) -> u16 {
109 self.initializer()
110 .get("status")
111 .and_then(|v| v.as_u64())
112 .unwrap_or(0) as u16
113 }
114
115 pub fn status_text(&self) -> &str {
119 self.initializer()
120 .get("statusText")
121 .and_then(|v| v.as_str())
122 .unwrap_or("")
123 }
124
125 pub fn url(&self) -> &str {
129 self.initializer()
130 .get("url")
131 .and_then(|v| v.as_str())
132 .unwrap_or("")
133 }
134
135 pub async fn body(&self) -> Result<Vec<u8>> {
142 use serde::Deserialize;
143
144 #[derive(Deserialize)]
145 struct BodyResponse {
146 binary: String,
147 }
148
149 let result: BodyResponse = self.channel().send("body", serde_json::json!({})).await?;
150
151 use base64::Engine;
152 let bytes = base64::engine::general_purpose::STANDARD
153 .decode(&result.binary)
154 .map_err(|e| {
155 crate::error::Error::ProtocolError(format!(
156 "Failed to decode response body from base64: {}",
157 e
158 ))
159 })?;
160 Ok(bytes)
161 }
162
163 pub async fn security_details(&self) -> Result<Option<SecurityDetails>> {
167 let result: serde_json::Value = self
168 .channel()
169 .send("securityDetails", serde_json::json!({}))
170 .await?;
171
172 let value = result.get("value");
173 match value {
174 Some(v) if v.is_object() && !v.as_object().unwrap().is_empty() => {
175 Ok(Some(SecurityDetails {
176 issuer: v.get("issuer").and_then(|v| v.as_str()).map(String::from),
177 protocol: v.get("protocol").and_then(|v| v.as_str()).map(String::from),
178 subject_name: v
179 .get("subjectName")
180 .and_then(|v| v.as_str())
181 .map(String::from),
182 valid_from: v.get("validFrom").and_then(|v| v.as_f64()),
183 valid_to: v.get("validTo").and_then(|v| v.as_f64()),
184 }))
185 }
186 _ => Ok(None),
187 }
188 }
189
190 pub async fn server_addr(&self) -> Result<Option<RemoteAddr>> {
194 let result: serde_json::Value = self
195 .channel()
196 .send("serverAddr", serde_json::json!({}))
197 .await?;
198
199 let value = result.get("value");
200 match value {
201 Some(v) if !v.is_null() => {
202 let ip_address = v
203 .get("ipAddress")
204 .and_then(|v| v.as_str())
205 .unwrap_or("")
206 .to_string();
207 let port = v.get("port").and_then(|v| v.as_u64()).unwrap_or(0) as u16;
208 Ok(Some(RemoteAddr { ip_address, port }))
209 }
210 _ => Ok(None),
211 }
212 }
213
214 pub async fn sizes(&self) -> Result<RequestSizes> {
218 use serde::Deserialize;
219
220 #[derive(Deserialize)]
221 #[serde(rename_all = "camelCase")]
222 struct SizesRaw {
223 request_body_size: i64,
224 request_headers_size: i64,
225 response_body_size: i64,
226 response_headers_size: i64,
227 }
228
229 #[derive(Deserialize)]
230 struct RpcResult {
231 sizes: SizesRaw,
232 }
233
234 let result: RpcResult = self.channel().send("sizes", serde_json::json!({})).await?;
235
236 Ok(RequestSizes {
237 request_body_size: result.sizes.request_body_size,
238 request_headers_size: result.sizes.request_headers_size,
239 response_body_size: result.sizes.response_body_size,
240 response_headers_size: result.sizes.response_headers_size,
241 })
242 }
243
244 pub async fn raw_headers(&self) -> Result<Vec<HeaderEntry>> {
250 use serde::Deserialize;
251
252 #[derive(Deserialize)]
253 struct RawHeadersResponse {
254 headers: Vec<HeaderEntryRaw>,
255 }
256
257 #[derive(Deserialize)]
258 struct HeaderEntryRaw {
259 name: String,
260 value: String,
261 }
262
263 let result: RawHeadersResponse = self
264 .channel()
265 .send("rawResponseHeaders", serde_json::json!({}))
266 .await?;
267
268 Ok(result
269 .headers
270 .into_iter()
271 .map(|h| HeaderEntry {
272 name: h.name,
273 value: h.value,
274 })
275 .collect())
276 }
277}
278
279impl ChannelOwner for ResponseObject {
280 fn guid(&self) -> &str {
281 self.base.guid()
282 }
283
284 fn type_name(&self) -> &str {
285 self.base.type_name()
286 }
287
288 fn parent(&self) -> Option<Arc<dyn ChannelOwner>> {
289 self.base.parent()
290 }
291
292 fn connection(&self) -> Arc<dyn crate::server::connection::ConnectionLike> {
293 self.base.connection()
294 }
295
296 fn initializer(&self) -> &Value {
297 self.base.initializer()
298 }
299
300 fn channel(&self) -> &crate::server::channel::Channel {
301 self.base.channel()
302 }
303
304 fn dispose(&self, reason: crate::server::channel_owner::DisposeReason) {
305 self.base.dispose(reason)
306 }
307
308 fn adopt(&self, child: Arc<dyn ChannelOwner>) {
309 self.base.adopt(child)
310 }
311
312 fn add_child(&self, guid: Arc<str>, child: Arc<dyn ChannelOwner>) {
313 self.base.add_child(guid, child)
314 }
315
316 fn remove_child(&self, guid: &str) {
317 self.base.remove_child(guid)
318 }
319
320 fn on_event(&self, _method: &str, _params: Value) {
321 }
323
324 fn was_collected(&self) -> bool {
325 self.base.was_collected()
326 }
327
328 fn as_any(&self) -> &dyn Any {
329 self
330 }
331}
332
333impl std::fmt::Debug for ResponseObject {
334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
335 f.debug_struct("ResponseObject")
336 .field("guid", &self.guid())
337 .finish()
338 }
339}