fix(cdp): emit Network events for script-initiated requests (#415)
Requests made by page JS (fetch/XHR/dynamic script and stylesheet loads)
run in the V8 op layer and never produced a NetworkEvent, so CDP emitted
Network.requestWillBeSent / responseReceived only for the static
navigation subresources. Puppeteer/Playwright page.on('request') and
on('response') therefore missed every XHR/JSON response, which breaks
response capture (and is the root cause of the Aviasales half of #394).
op_fetch_url now records a JsNetworkEvent keyed by the same fetch-{N} id
under which it already stores the response body. The Page drains these
into its network_events before the CDP layer emits, so they flow through
emit_navigation_events as requestWillBeSent / responseReceived /
loadingFinished alongside the document subresources, and
Network.getResponseBody resolves for them via the shared id. Applied to
both navigation paths (server process_navigation and in-process
do_navigate). The queue is capped at 4096 events per page.
Closes #406.
This commit is contained in:
1 parent
b460b37e93
commit
d0b6fc4ffd
6 files changed
+270
No files matched your search
@@ -1256,6 +1256,32 @@ impl Page {
|
||||
self.js.as_ref().map(|js| js.fetched_urls()).unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Move network events recorded for script-initiated requests
|
||||
/// (fetch/XHR/dynamic resource) from the JS runtime into this page's
|
||||
/// network_events, so the CDP layer emits Network.requestWillBeSent /
|
||||
/// responseReceived for them (issue #406). Idempotent: the runtime's queue
|
||||
/// is drained, so calling this repeatedly does not duplicate events. The
|
||||
/// fetch-{N} request id is preserved so Network.getResponseBody resolves.
|
||||
pub fn sync_js_network_events(&mut self) {
|
||||
let events = match self.js.as_ref() {
|
||||
Some(js) => js.take_js_network_events(),
|
||||
None => return,
|
||||
};
|
||||
for ev in events {
|
||||
self.network_events.push(NetworkEvent {
|
||||
request_id: ev.request_id,
|
||||
url: ev.url,
|
||||
method: ev.method,
|
||||
resource_type: "Fetch".to_string(),
|
||||
status: ev.status,
|
||||
headers: std::collections::HashMap::new(),
|
||||
response_headers: Arc::new(ev.response_headers),
|
||||
body_size: ev.body_size,
|
||||
timestamp: ev.timestamp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dom(&self) -> Option<&DomTree> {
|
||||
self.dom.as_ref()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user