From fba460a53e1a6496dce4262a7d5778f55da3e250 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Sun, 17 Dec 2023 17:47:22 -0300 Subject: [PATCH 1/3] Log raw WS messages to facilitate the debugging --- src/conn.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/conn.rs b/src/conn.rs index 46d04b5d..ddf53ff5 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -136,22 +136,28 @@ impl Stream for Connection { } // read from the ws - match ready!(pin.ws.poll_next_unpin(cx)) { - Some(Ok(msg)) => match serde_json::from_slice::>(&msg.into_data()) { + let msg = match ready!(pin.ws.poll_next_unpin(cx)) { + Some(Ok(msg)) => msg, + Some(Err(err)) => return Poll::Ready(Some(Err(CdpError::Ws(err)))), + None => { + // ws connection closed + return Poll::Ready(None); + } + }; + + tracing::trace!(target: "chromiumoxide::conn::raw_ws", ?msg, "Got raw WS message"); + + Poll::Ready(Some( + match serde_json::from_slice::>(&msg.into_data()) { Ok(msg) => { tracing::trace!("Received {:?}", msg); - Poll::Ready(Some(Ok(msg))) + Ok(msg) } Err(err) => { tracing::error!("Failed to deserialize WS response {}", err); - Poll::Ready(Some(Err(err.into()))) + Err(err.into()) } }, - Some(Err(err)) => Poll::Ready(Some(Err(CdpError::Ws(err)))), - None => { - // ws connection closed - Poll::Ready(None) - } - } + )) } } From fa58a28dac1fab423017f5d3fd9f011ee2d0f5a9 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Sun, 17 Dec 2023 18:39:21 -0300 Subject: [PATCH 2/3] Add debug-raw-ws-messages feature --- Cargo.toml | 2 ++ src/conn.rs | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index ff72856b..8c544c0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,8 @@ _fetcher-rusttls-tokio = ["fetcher", "chromiumoxide_fetcher/_rustls-tokio"] _fetcher-native-async-std = ["fetcher", "chromiumoxide_fetcher/_native-async-std"] _fetcher-native-tokio = ["fetcher", "chromiumoxide_fetcher/_native-tokio"] +debug-raw-ws-messages = [] + [[example]] name = "wiki-tokio" required-features = ["tokio-runtime"] diff --git a/src/conn.rs b/src/conn.rs index ddf53ff5..5b8e40b4 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -147,6 +147,9 @@ impl Stream for Connection { tracing::trace!(target: "chromiumoxide::conn::raw_ws", ?msg, "Got raw WS message"); + #[cfg(feature = "debug-raw-ws-messages")] + let msg_for_debug = msg.clone(); + Poll::Ready(Some( match serde_json::from_slice::>(&msg.into_data()) { Ok(msg) => { @@ -154,6 +157,9 @@ impl Stream for Connection { Ok(msg) } Err(err) => { + #[cfg(feature = "debug-raw-ws-messages")] + tracing::debug!(target: "chromiumoxide::conn::raw_ws::parse_errors", msg = ?msg_for_debug, "Failed to parse raw WS message"); + tracing::error!("Failed to deserialize WS response {}", err); Err(err.into()) } From 7903f84f0dc0c7181df61dd7109a82b3e81fe710 Mon Sep 17 00:00:00 2001 From: MOZGIII Date: Sun, 17 Dec 2023 18:18:37 -0300 Subject: [PATCH 3/3] Test cases for message parsing --- src/conn.rs | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/src/conn.rs b/src/conn.rs index 5b8e40b4..35474b1c 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -167,3 +167,121 @@ impl Stream for Connection { )) } } + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLES: &[&str] = &[r#"{ + "method": "Network.responseReceivedExtraInfo", + "params": { + "requestId": "...", + "blockedCookies": [ + { + "blockedReasons": [ + "SameSiteUnspecifiedTreatedAsLax" + ], + "cookieLine": "...=5; expires=Mon, 18 Dec 2023 01:25:44 GMT; Max-Age=3600; Path=/", + "cookie": { + "name": "...", + "value": "5", + "domain": "...", + "path": "/", + "expires": 1702862744.118586, + "size": 21, + "httpOnly": false, + "secure": false, + "session": false, + "priority": "Medium", + "sameParty": false, + "sourceScheme": "Secure", + "sourcePort": 443 + } + }, + { + "blockedReasons": [ + "SameSiteUnspecifiedTreatedAsLax" + ], + "cookieLine": "...=\"\"; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/", + "cookie": { + "name": "...", + "value": "\"\"", + "domain": "...", + "path": "/", + "expires": null, + "size": 20, + "httpOnly": false, + "secure": false, + "session": false, + "priority": "Medium", + "sameParty": false, + "sourceScheme": "Secure", + "sourcePort": 443 + } + }, + { + "blockedReasons": [ + "SameSiteUnspecifiedTreatedAsLax" + ], + "cookieLine": "...=\"\"; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/", + "cookie": { + "name": "...", + "value": "\"\"", + "domain": "...", + "path": "/", + "expires": null, + "size": 11, + "httpOnly": false, + "secure": false, + "session": false, + "priority": "Medium", + "sameParty": false, + "sourceScheme": "Secure", + "sourcePort": 443 + } + }, + { + "blockedReasons": [ + "SameSiteUnspecifiedTreatedAsLax" + ], + "cookieLine": "...=\"\"; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/", + "cookie": { + "name": "...", + "value": "\"\"", + "domain": "...", + "path": "/", + "expires": null, + "size": 12, + "httpOnly": false, + "secure": false, + "session": false, + "priority": "Medium", + "sameParty": false, + "sourceScheme": "Secure", + "sourcePort": 443 + } + } + ], + "headers": { + "server": "cloudflare", + "more": "redacted" + }, + "resourceIPAddressSpace": "Public", + "statusCode": 200, + "cookiePartitionKey": "https://...", + "cookiePartitionKeyOpaque": false + }, + "sessionId": "2B3589AF08CFD7B319297F7D3E57FAEF" + }"#]; + + #[test] + fn parses_without_error() { + for sample in SAMPLES { + let _message: Message = + match serde_json::from_str(sample) { + Ok(val) => val, + Err(error) => panic!("Failed to parse the message:\n{error}\n{sample}",), + }; + } + } +}