google / google/capsem

[triage:tooling-01-delayed-chunks-identical-no-delay-no-chunking] `/delayed-chunks` and `/chunked` are byte-identical, buffered, and never chunked or delayed

Open
#145 0 comments 0 reactions 0 assignees View on GitHub
type:bug
Dominant language
Rust
Stars
72
Forks
13
Avg merge
1d 2h
Merged PRs (30d)
5

Description

Imported from Capsem triage report `tooling-01-delayed-chunks-identical-no-delay-no-chunking.md`.

- Severity: `medium`
- Category: `bug (mock divergence)`
- Area: `capsem-mock-server`
- Location: `crates/capsem-mock-server/src/main.rs:414-418`
- Confidence: `verified`

## Summary
The mock advertises two distinct streaming-shaped endpoints, `/chunked` and `/delayed-chunks`, but they share a single route arm that returns one fully-buffered body with a fixed `Content-Length` and no inter-chunk delay. Tests that depend on either chunked transfer-encoding *or* a time gap between chunks (the two behaviors the endpoint names promise) will pass against a mock that exhibits neither, masking real proxy bugs in chunk reassembly and timing.

## Evidence
```rust
(&Method::GET, "/chunked") | (&Method::GET, "/delayed-chunks") => response(
StatusCode::OK,
Bytes::from_static(b"chunk-0\nchunk-1\nchunk-2\nchunk-3\n"),
"text/plain; charset=utf-8",
),
```
`response()` (line 639) calls `response_builder()` (line 678), which unconditionally sets `CONTENT_TYPE` and `CONTENT_LENGTH` headers, and wraps the body in `Full::new(body)` (line 689). A `Full` body with an explicit `Content-Length` is delivered as a single non-chunked HTTP/1.1 response. No `tokio::time::sleep` is present on this path, unlike `/mcp` (line 547) which does delay via `mcp_payload_should_delay`. So:
- `/delayed-chunks` introduces zero delay — identical wall behavior to `/chunked`.
- Neither uses `Transfer-Encoding: chunked`; both send `Content-Length: 32`.

## Impact
The MITM proxy's chunk-boundary and streaming-timeout handling is exercised by these endpoints. A buffered, length-delimited single body cannot reproduce: partial-chunk buffering, chunk framing parse, or read-timeout-between-chunks logic. A regression in the proxy's chunked-stream path would not be caught by tests hitting these endpoints, because the mock never actually chunks or delays.

## Suggested fix
Make `/chunked` emit a real `Transfer-Encoding: chunked` body (e.g. a `StreamBody`/`channel` body with multiple frames and no `Content-Length`), and make `/delayed-chunks` insert a `tokio::time::sleep` between frames. At minimum, split the two arms so `/delayed-chunks` delays. If chunked streaming is genuinely out of scope, rename/remove the endpoints so the advertised contract matches behavior.

## Triage
Confirmed from the local reviewed report in `/Users/elie/git/capsem/tmp/bugs/tooling-01-delayed-chunks-identical-no-delay-no-chunking.md`. Track implementation in the triage sprint; add regression coverage before fixing.

Contributor guide

Open the contributing guide

Research direction

Start in crates/capsem-mock-server/src/main.rs at the route arms around lines 414-418, then read response() and response_builder() around lines 639-689 and compare the /mcp delay path near line 547. Add regression coverage before changing the mock. Done means the advertised chunking and delayed-chunk behaviors are observable, or the endpoints are renamed or removed to match their actual contract.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
networking, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.