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 #[tracing::instrument(level = "debug", skip_all, fields(guid = %self.guid(), bytes_len = tracing::field::Empty))]
142 pub async fn body(&self) -> Result<Vec<u8>> {
143 use serde::Deserialize;
144
145 #[derive(Deserialize)]
146 struct BodyResponse {
147 binary: String,
148 }
149
150 let result: BodyResponse = self.channel().send("body", serde_json::json!({})).await?;
151
152 use base64::Engine;
153 let bytes = base64::engine::general_purpose::STANDARD
154 .decode(&result.binary)
155 .map_err(|e| {
156 crate::error::Error::ProtocolError(format!(
157 "Failed to decode response body from base64: {}",
158 e
159 ))
160 })?;
161 Ok(bytes)
162 }
163
164 #[tracing::instrument(level = "debug", skip_all, fields(guid = %self.guid()))]
168 pub async fn security_details(&self) -> Result<Option<SecurityDetails>> {
169 let result: serde_json::Value = self
170 .channel()
171 .send("securityDetails", serde_json::json!({}))
172 .await?;
173
174 let value = result.get("value");
175 match value {
176 Some(v) if v.as_object().is_some_and(|obj| !obj.is_empty()) => {
177 Ok(Some(SecurityDetails {
178 issuer: v.get("issuer").and_then(|v| v.as_str()).map(String::from),
179 protocol: v.get("protocol").and_then(|v| v.as_str()).map(String::from),
180 subject_name: v
181 .get("subjectName")
182 .and_then(|v| v.as_str())
183 .map(String::from),
184 valid_from: v.get("validFrom").and_then(|v| v.as_f64()),
185 valid_to: v.get("validTo").and_then(|v| v.as_f64()),
186 }))
187 }
188 _ => Ok(None),
189 }
190 }
191
192 #[tracing::instrument(level = "debug", skip_all, fields(guid = %self.guid()))]
196 pub async fn server_addr(&self) -> Result<Option<RemoteAddr>> {
197 let result: serde_json::Value = self
198 .channel()
199 .send("serverAddr", serde_json::json!({}))
200 .await?;
201
202 let value = result.get("value");
203 match value {
204 Some(v) if !v.is_null() => {
205 let ip_address = v
206 .get("ipAddress")
207 .and_then(|v| v.as_str())
208 .unwrap_or("")
209 .to_string();
210 let port = v.get("port").and_then(|v| v.as_u64()).unwrap_or(0) as u16;
211 Ok(Some(RemoteAddr { ip_address, port }))
212 }
213 _ => Ok(None),
214 }
215 }
216
217 #[tracing::instrument(level = "debug", skip_all, fields(guid = %self.guid()))]
221 pub async fn sizes(&self) -> Result<RequestSizes> {
222 use serde::Deserialize;
223
224 #[derive(Deserialize)]
225 #[serde(rename_all = "camelCase")]
226 struct SizesRaw {
227 request_body_size: i64,
228 request_headers_size: i64,
229 response_body_size: i64,
230 response_headers_size: i64,
231 }
232
233 #[derive(Deserialize)]
234 struct RpcResult {
235 sizes: SizesRaw,
236 }
237
238 let result: RpcResult = self.channel().send("sizes", serde_json::json!({})).await?;
239
240 Ok(RequestSizes {
241 request_body_size: result.sizes.request_body_size,
242 request_headers_size: result.sizes.request_headers_size,
243 response_body_size: result.sizes.response_body_size,
244 response_headers_size: result.sizes.response_headers_size,
245 })
246 }
247
248 #[tracing::instrument(level = "debug", skip_all, fields(guid = %self.guid(), version = tracing::field::Empty))]
254 pub async fn http_version(&self) -> Result<String> {
255 use serde::Deserialize;
256
257 #[derive(Deserialize)]
258 struct HttpVersionResponse {
259 value: String,
260 }
261
262 let result: HttpVersionResponse = self
263 .channel()
264 .send("httpVersion", serde_json::json!({}))
265 .await?;
266 Ok(result.value)
267 }
268
269 #[tracing::instrument(level = "debug", skip_all, fields(guid = %self.guid()))]
275 pub async fn raw_headers(&self) -> Result<Vec<HeaderEntry>> {
276 use serde::Deserialize;
277
278 #[derive(Deserialize)]
279 struct RawHeadersResponse {
280 headers: Vec<HeaderEntryRaw>,
281 }
282
283 #[derive(Deserialize)]
284 struct HeaderEntryRaw {
285 name: String,
286 value: String,
287 }
288
289 let result: RawHeadersResponse = self
290 .channel()
291 .send("rawResponseHeaders", serde_json::json!({}))
292 .await?;
293
294 Ok(result
295 .headers
296 .into_iter()
297 .map(|h| HeaderEntry {
298 name: h.name,
299 value: h.value,
300 })
301 .collect())
302 }
303}
304
305impl ChannelOwner for ResponseObject {
306 fn guid(&self) -> &str {
307 self.base.guid()
308 }
309
310 fn type_name(&self) -> &str {
311 self.base.type_name()
312 }
313
314 fn parent(&self) -> Option<Arc<dyn ChannelOwner>> {
315 self.base.parent()
316 }
317
318 fn connection(&self) -> Arc<dyn crate::server::connection::ConnectionLike> {
319 self.base.connection()
320 }
321
322 fn initializer(&self) -> &Value {
323 self.base.initializer()
324 }
325
326 fn channel(&self) -> &crate::server::channel::Channel {
327 self.base.channel()
328 }
329
330 fn dispose(&self, reason: crate::server::channel_owner::DisposeReason) {
331 self.base.dispose(reason)
332 }
333
334 fn adopt(&self, child: Arc<dyn ChannelOwner>) {
335 self.base.adopt(child)
336 }
337
338 fn add_child(&self, guid: Arc<str>, child: Arc<dyn ChannelOwner>) {
339 self.base.add_child(guid, child)
340 }
341
342 fn remove_child(&self, guid: &str) {
343 self.base.remove_child(guid)
344 }
345
346 fn on_event(&self, _method: &str, _params: Value) {
347 }
349
350 fn was_collected(&self) -> bool {
351 self.base.was_collected()
352 }
353
354 fn as_any(&self) -> &dyn Any {
355 self
356 }
357}
358
359impl std::fmt::Debug for ResponseObject {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 f.debug_struct("ResponseObject")
362 .field("guid", &self.guid())
363 .finish()
364 }
365}