Conversation
There was a problem hiding this comment.
Pull request overview
Adds optional “sample response” capture to the probe_endpoints command so callers can retrieve example payloads from OpenAPI specs and (heuristically) capture a live REST response body for discovered REST endpoints.
Changes:
- Added
capture_samplesflag toProbeEndpointsCommand(defaults tofalse). - Extended OpenAPI probing to optionally attach
sample_responseper operation (via newextract_response_examplehelper). - Extended REST heuristic probing to optionally attach a
sample_responseat the endpoint level and added unit tests covering the new behavior.
| /// Extract a sample response from an OpenAPI operation's response schema. | ||
| /// Looks for: responses -> 200 -> content -> application/json -> example/schema/examples | ||
| fn extract_response_example(spec: &Value, operation: &Value) -> Option<Value> { | ||
| let responses = operation.get("responses")?; | ||
|
|
||
| // Try 200, 201, then default | ||
| let response = responses | ||
| .get("200") | ||
| .or_else(|| responses.get("201")) | ||
| .or_else(|| responses.get("default"))?; | ||
|
|
There was a problem hiding this comment.
extract_response_example is compiled unconditionally, but it is only used from extract_openapi_operations, which is behind #[cfg(any(feature = "docker", test))]. In a --no-default-features --features minimal build, this function will be unused and is likely to trigger a dead_code warning (and fail CI when running clippy with -D warnings). Consider gating extract_response_example with the same cfg(any(feature = "docker", test)) (or adding an allow(dead_code) under not(feature="docker")) to keep minimal builds warning-free.
| // Capture sample response body for REST endpoints | ||
| let mut sample_response = None; | ||
| if data.capture_samples && code == "200" { | ||
| let body_cmd = format!( | ||
| "curl -sf -m {} http://localhost:{}{} 2>/dev/null || true", | ||
| data.probe_timeout, port, path | ||
| ); | ||
| if let Ok(Ok((0, body, _))) = tokio::time::timeout( | ||
| std::time::Duration::from_secs((data.probe_timeout + 2) as u64), | ||
| docker::exec_in_container_with_output(&target_name, &body_cmd), | ||
| ) | ||
| .await | ||
| { | ||
| let body = body.trim(); | ||
| if !body.is_empty() { | ||
| // Try to parse as JSON; fall back to string | ||
| sample_response = Some( | ||
| serde_json::from_str::<Value>(body) | ||
| .unwrap_or_else(|_| json!(body)), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Capturing REST sample_response via curl has no response-size limit, so a /api endpoint that returns a large payload (or unexpected binary/HTML) can significantly increase memory usage and the size of the command result returned to the controller. Consider adding a hard cap (e.g., fetch only the first N bytes), and optionally applying the existing redact_message logic before attaching the sample to the result to reduce risk of leaking secrets.
No description provided.