servo/components/devtools/network_handler.rs
Usman Yahaya Baba ff02fdad6d
Send early DevToolsHttpRequest and relocate response reporting to main_fetch (#37906)
This change refactors how we notify DevTools about network activity so
that all fetches (even those served from cache) appear correctly in the
Network panel, and so that DevTools sees request metadata as soon as
possible rather than waiting until the end of a full HTTP cycle.
- Before, we only send DevTools events inside http_network_fetch, so
cached responses (which skip that path) never show up. By emitting a
minimal HttpRequest event at the very start of main_fetch (with URL,
method, pipeline and browsing IDs), we guarantee every fetch shows up
immediately.
- Then, by moving HttpResponse notifications out of http_network_fetch
into main_fetch (right after process_response and process_response_eof),
we ensure DevTools gets status, header, and completion events for both
network and cache hits. Leveraging nullable fields in NetworkEventActor
lets us incrementally fill in timing, header, and body data later,
improving DevTools’ visibility.
Testing: Ran servo with `--devtools=6080` flag, cached responses now
appear in the network panel
Fixes: https://github.com/servo/servo/issues/37869

---------

Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
2025-07-15 05:41:11 +00:00

89 lines
3 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::net::TcpStream;
use std::sync::{Arc, Mutex};
use devtools_traits::NetworkEvent;
use serde::Serialize;
use crate::actor::ActorRegistry;
use crate::actors::network_event::NetworkEventActor;
use crate::actors::watcher::WatcherActor;
use crate::resource::{ResourceArrayType, ResourceAvailable};
#[derive(Clone, Serialize)]
pub struct Cause {
#[serde(rename = "type")]
pub type_: String,
#[serde(rename = "loadingDocumentUri")]
pub loading_document_uri: Option<String>,
}
pub(crate) fn handle_network_event(
actors: Arc<Mutex<ActorRegistry>>,
netevent_actor_name: String,
mut connections: Vec<TcpStream>,
network_event: NetworkEvent,
) {
let mut actors = actors.lock().unwrap();
let actor = actors.find_mut::<NetworkEventActor>(&netevent_actor_name);
let watcher_name = actor.watcher_name.clone();
match network_event {
NetworkEvent::HttpRequest(httprequest) => {
actor.add_request(httprequest);
let event_actor = actor.event_actor();
let resource_updates = actor.resource_updates();
let watcher_actor = actors.find::<WatcherActor>(&watcher_name);
for stream in &mut connections {
watcher_actor.resource_array(
event_actor.clone(),
"network-event".to_string(),
ResourceArrayType::Available,
stream,
);
// Also push initial resource update (request headers, cookies)
watcher_actor.resource_array(
resource_updates.clone(),
"network-event".to_string(),
ResourceArrayType::Updated,
stream,
);
}
},
NetworkEvent::HttpRequestUpdate(httprequest) => {
actor.add_request(httprequest);
let resource = actor.resource_updates();
let watcher_actor = actors.find::<WatcherActor>(&watcher_name);
for stream in &mut connections {
watcher_actor.resource_array(
resource.clone(),
"network-event".to_string(),
ResourceArrayType::Updated,
stream,
);
}
},
NetworkEvent::HttpResponse(httpresponse) => {
// Store the response information in the actor
actor.add_response(httpresponse);
let resource = actor.resource_updates();
let watcher_actor = actors.find::<WatcherActor>(&watcher_name);
for stream in &mut connections {
watcher_actor.resource_array(
resource.clone(),
"network-event".to_string(),
ResourceArrayType::Updated,
stream,
);
}
},
}
}