feat: add network request detail and filtering for request tracking (#935)
* feat: add network request detail and filtering for request tracking - Add `network request <requestId>` command to view full request/response details including response body via CDP Network.getResponseBody - Add --type, --method, --status filter flags to `network requests` - --type: comma-separated resource types (xhr,fetch,document) - --method: filter by HTTP method - --status: supports exact (200), class (2xx), range (400-499) - Extend TrackedRequest with request_id, post_data, status, response_headers, mime_type fields - Update Network.responseReceived handler to also populate tracked_requests (previously only updated HAR entries) - Add tests for parse commands and matches_status_filter - Update README, SKILL.md, docs, and help text Closes #932 * fix: show request ID and status in network requests output
This commit is contained in:
+72
-2
@@ -2078,7 +2078,7 @@ fn parse_set(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
||||
|
||||
/// Parse network interception, request inspection, and HAR recording commands.
|
||||
fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
||||
const VALID: &[&str] = &["route", "unroute", "requests", "har"];
|
||||
const VALID: &[&str] = &["route", "unroute", "requests", "request", "har"];
|
||||
|
||||
match rest.first().copied() {
|
||||
Some("route") => {
|
||||
@@ -2102,12 +2102,34 @@ fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
||||
let clear = rest.contains(&"--clear");
|
||||
let filter_idx = rest.iter().position(|&s| s == "--filter");
|
||||
let filter = filter_idx.and_then(|i| rest.get(i + 1).copied());
|
||||
let type_idx = rest.iter().position(|&s| s == "--type");
|
||||
let rtype = type_idx.and_then(|i| rest.get(i + 1).copied());
|
||||
let method_idx = rest.iter().position(|&s| s == "--method");
|
||||
let method = method_idx.and_then(|i| rest.get(i + 1).copied());
|
||||
let status_idx = rest.iter().position(|&s| s == "--status");
|
||||
let status = status_idx.and_then(|i| rest.get(i + 1).copied());
|
||||
let mut cmd = json!({ "id": id, "action": "requests", "clear": clear });
|
||||
if let Some(f) = filter {
|
||||
cmd["filter"] = json!(f);
|
||||
}
|
||||
if let Some(t) = rtype {
|
||||
cmd["type"] = json!(t);
|
||||
}
|
||||
if let Some(m) = method {
|
||||
cmd["method"] = json!(m);
|
||||
}
|
||||
if let Some(s) = status {
|
||||
cmd["status"] = json!(s);
|
||||
}
|
||||
Ok(cmd)
|
||||
}
|
||||
Some("request") => {
|
||||
let request_id = rest.get(1).ok_or_else(|| ParseError::MissingArguments {
|
||||
context: "network request".to_string(),
|
||||
usage: "network request <requestId>",
|
||||
})?;
|
||||
Ok(json!({ "id": id, "action": "request_detail", "requestId": request_id }))
|
||||
}
|
||||
Some("har") => {
|
||||
const HAR_VALID: &[&str] = &["start", "stop"];
|
||||
match rest.get(1).copied() {
|
||||
@@ -2135,7 +2157,7 @@ fn parse_network(rest: &[&str], id: &str) -> Result<Value, ParseError> {
|
||||
}),
|
||||
None => Err(ParseError::MissingArguments {
|
||||
context: "network".to_string(),
|
||||
usage: "network <route|unroute|requests|har> [args...]",
|
||||
usage: "network <route|unroute|requests|request|har> [args...]",
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -2742,6 +2764,54 @@ mod tests {
|
||||
assert!(matches!(result, Err(ParseError::MissingArguments { .. })));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_network_requests_type_filter() {
|
||||
let cmd =
|
||||
parse_command(&args("network requests --type xhr,fetch"), &default_flags()).unwrap();
|
||||
assert_eq!(cmd["action"], "requests");
|
||||
assert_eq!(cmd["type"], "xhr,fetch");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_network_requests_method_filter() {
|
||||
let cmd = parse_command(&args("network requests --method POST"), &default_flags()).unwrap();
|
||||
assert_eq!(cmd["action"], "requests");
|
||||
assert_eq!(cmd["method"], "POST");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_network_requests_status_filter() {
|
||||
let cmd = parse_command(&args("network requests --status 2xx"), &default_flags()).unwrap();
|
||||
assert_eq!(cmd["action"], "requests");
|
||||
assert_eq!(cmd["status"], "2xx");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_network_requests_combined_filters() {
|
||||
let cmd = parse_command(
|
||||
&args("network requests --filter api --type xhr --method GET --status 200"),
|
||||
&default_flags(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(cmd["filter"], "api");
|
||||
assert_eq!(cmd["type"], "xhr");
|
||||
assert_eq!(cmd["method"], "GET");
|
||||
assert_eq!(cmd["status"], "200");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_network_request_detail() {
|
||||
let cmd = parse_command(&args("network request 1234.5"), &default_flags()).unwrap();
|
||||
assert_eq!(cmd["action"], "request_detail");
|
||||
assert_eq!(cmd["requestId"], "1234.5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_network_request_detail_requires_id() {
|
||||
let result = parse_command(&args("network request"), &default_flags());
|
||||
assert!(matches!(result, Err(ParseError::MissingArguments { .. })));
|
||||
}
|
||||
|
||||
// === Screenshot ===
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user