headroom/tests/test_proxy
Rod Boev 3be2526b76
fix(proxy): add an Anthropic buffered read-timeout override (#1331)
## Description

Buffered Anthropic `/v1/messages` requests still use Headroom's generic
300-second read timeout, which can produce proxy-generated `502
ReadTimeout` errors on long turns. This adds a dedicated buffered
Anthropic timeout, keeps it applied across CCR and memory continuations
plus batch paths, and makes the direct server entrypoint enforce the
same positive-integer contract as the Click CLI. Closes #1261.

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)

## Changes Made

- Added `anthropic_buffered_request_timeout_seconds` for buffered
Anthropic reads.
- Routed `/v1/messages`, CCR continuation, memory continuation, batch
create, batch passthrough, and batch results through that timeout.
- Enforced the same positive-integer validation for
`HEADROOM_ANTHROPIC_BUFFERED_REQUEST_TIMEOUT_SECONDS` and
`--anthropic-buffered-request-timeout-seconds` in both startup paths.
- Added focused regressions and updated `CHANGELOG.md`.

## Testing

- [x] `uv run pytest tests/test_proxy/test_anthropic_buffered_timeout.py
tests/test_cli_proxy_improvements.py::TestNewEnvVarWiring`
- [x] `uv run ruff check .`
- [x] `uv run ruff format . --check`

### Test Output

```text
$ uv run pytest tests/test_proxy/test_anthropic_buffered_timeout.py tests/test_cli_proxy_improvements.py::TestNewEnvVarWiring
17 passed in 3.42s

$ uv run ruff check .
All checks passed!

$ uv run ruff format . --check
966 files already formatted
```

## Real Behavior Proof

- Environment: local FastAPI `TestClient` with stubbed retry and HTTP
client seams
- Exact command / steps: run `uv run pytest
tests/test_proxy/test_anthropic_buffered_timeout.py
tests/test_cli_proxy_improvements.py::TestNewEnvVarWiring`; the tests
build `ProxyConfig(request_timeout_seconds=7, connect_timeout_seconds=3,
anthropic_buffered_request_timeout_seconds=19)`, drive `/v1/messages`,
`/v1/messages/batches`, `/v1/messages/batches/{batch_id}/results`, a CCR
continuation, and a memory continuation through `TestClient`, then
verify `HEADROOM_ANTHROPIC_BUFFERED_REQUEST_TIMEOUT_SECONDS=0` falls
back to `600`, `--anthropic-buffered-request-timeout-seconds 0` is
rejected, and default proxy timeouts stay `read=300` and `write=300`
- Observed result: buffered Anthropic paths use
`httpx.Timeout(connect=3, read=19, write=7, pool=3)`, continuation
requests stay on that same budget, invalid zero-valued startup config is
rejected or ignored back to the default, and unrelated proxy timeout
defaults stay unchanged
- Not tested: live upstream Anthropic latency beyond the focused
stubbed-timeout regression

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have added tests that prove the fix
- [x] New and existing unit tests pass locally with my changes
- [x] I have updated the CHANGELOG.md if applicable
2026-06-23 22:46:31 -05:00
..
test_anthropic_buffered_timeout.py fix(proxy): add an Anthropic buffered read-timeout override (#1331) 2026-06-23 22:46:31 -05:00
test_anthropic_ccr_deferred_injection.py fix(ccr): skip Anthropic marker emission when tool injection is deferred (#1273) 2026-06-23 12:48:05 -05:00
test_anthropic_ccr_raise.py fix(anthropic): CCR exception must re-raise, not silently swallow (#838) 2026-06-10 21:11:46 -05:00
test_background_compression.py perf(compression): take large cold-start contexts off the synchronous kompress path (#1171) (#1298) 2026-06-23 10:48:06 -05:00
test_bedrock_passthrough.py feat(proxy): compress AWS Bedrock InvokeModel requests via configurable upstream (#720) 2026-06-16 14:56:16 -05:00
test_cc_switch_reconciler.py feat(proxy): cc-switch reconciler — keep Headroom in the request path alongside cc-switch (#1030) 2026-06-17 08:41:16 -05:00
test_compression_failure_action.py fix(codex): fail open for proxy compression timeout 2026-06-04 14:04:49 +05:30
test_compression_timeout_config.py feat(proxy): make COMPRESSION_TIMEOUT_SECONDS configurable via env (#946) (#991) 2026-06-16 21:10:01 -05:00
test_compute_turn_id.py fix(proxy): strip cache_control before hashing turn_id 2026-04-23 16:04:57 +02:00
test_header_safe_transforms.py feat(transforms): attribute read_lifecycle + smart_crush tags (#249) 2026-06-11 11:51:26 -05:00
test_mcp_stats_aggregation.py fix(proxy): Strands MCP bundle + backend path fixes + Codex fail-closed protection 2026-05-21 11:00:14 -07:00
test_openai_backend_path.py fix(proxy): Strands MCP bundle + backend path fixes + Codex fail-closed protection 2026-05-21 11:00:14 -07:00
test_phase3_byte_identity.py perf(compression): take large cold-start contexts off the synchronous kompress path (#1171) (#1298) 2026-06-23 10:48:06 -05:00
test_request_logger.py feat(proxy): log compressed messages alongside original request (#261) 2026-06-11 19:02:54 -05:00
test_transformations_feed.py fix(proxy): scope CORS to loopback + gate operator/content endpoints (#1226) 2026-06-21 00:50:55 -07:00