use playwright_rs::protocol::Playwright;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Network Events Example ===\n");
let playwright = Playwright::launch().await?;
let browser = playwright.chromium().launch().await?;
let page = browser.new_page().await?;
page.on_request(|request| async move {
println!(">> {} {}", request.method(), request.url());
Ok(())
})
.await?;
page.on_response(|response| async move {
println!(
"<< {} {} {}",
response.status(),
response.status_text(),
response.url()
);
Ok(())
})
.await?;
page.on_request_finished(|request| async move {
println!("-- finished: {}", request.url());
Ok(())
})
.await?;
page.on_request_failed(|request| async move {
println!("!! failed: {}", request.url());
Ok(())
})
.await?;
println!("Navigating to example.com...\n");
let waiter = page.expect_event("response", Some(10_000.0)).await?;
let response = page
.goto("https://example.com", None)
.await?
.expect("Expected a response");
waiter.wait().await?;
println!("\n=== Response Body Access ===\n");
let body_text = response.text().await?;
println!(
"Response text (first 80 chars): {}...",
&body_text[..body_text.len().min(80)]
);
let body_bytes = response.body().await?;
println!("Response body size: {} bytes", body_bytes.len());
if let Some(content_type) = response.header_value("content-type").await? {
println!("Content-Type: {}", content_type);
}
let headers = response.headers_array().await?;
println!("Response has {} header entries", headers.len());
println!("\n=== Back-references ===\n");
if let Some(request) = response.request() {
println!("Response request: {} {}", request.method(), request.url());
if let Some(frame) = request.frame() {
println!("Request frame URL: {}", frame.url());
}
}
if let Some(frame) = response.frame() {
println!("Response frame URL: {}", frame.url());
}
println!("\n=== Server Info ===\n");
if let Some(addr) = response.server_addr().await? {
println!("Server address: {}:{}", addr.ip_address, addr.port);
}
match response.security_details().await? {
Some(details) => {
println!("TLS protocol: {:?}", details.protocol);
println!("Certificate issuer: {:?}", details.issuer);
}
None => println!("No TLS (HTTP connection)"),
}
println!("\n=== Request -> Response & Sizes ===\n");
let page2 = browser.new_page().await?;
let captured = std::sync::Arc::new(std::sync::Mutex::new(None));
let captured_clone = captured.clone();
let notify = std::sync::Arc::new(tokio::sync::Notify::new());
let notify_clone = notify.clone();
page2
.on_request_finished(move |req| {
let cap = captured_clone.clone();
let n = notify_clone.clone();
async move {
if req.is_navigation_request() {
*cap.lock().unwrap() = Some(req);
n.notify_one();
}
Ok(())
}
})
.await?;
page2.goto("https://example.com", None).await?;
tokio::time::timeout(std::time::Duration::from_secs(10), notify.notified())
.await
.expect("request_finished handler did not fire");
let captured_req = captured.lock().unwrap().take();
if let Some(req) = captured_req {
if let Ok(Some(resp)) = req.response().await {
println!("request.response() status: {}", resp.status());
}
if let Ok(sizes) = req.sizes().await {
println!("Request headers size: {} bytes", sizes.request_headers_size);
println!("Response body size: {} bytes", sizes.response_body_size);
}
}
println!("\nClosing browser...");
browser.close().await?;
Ok(())
}