feat(net): hyper backend transport (hyper_leaf + build + TokioTimer)#90
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tokio-rustls as a dev-dependency and drive a real aws-lc-rs/webpki handshake in-crate: an rcgen self-signed cert served over a rustls loopback listener, and a HyperLeaf whose connector trusts exactly that cert (a custom RootCertStore, not webpki-roots). Also records a narrowly-scoped deny.toml license exception for webpki-roots' CDLA-Permissive-2.0 data license — the first time cargo-deny fully exercised the hyper/rustls/aws-lc dependency tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a new ChangesHyper backend transport crate
Estimated code review effort: 3 (Moderate) | ~30 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/adapter/net/http/hyper/src/error.rs (1)
24-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNo test coverage for
map_hyper_err(mid-stream body errors).The connect-timeout and aborted-connection tests in
leaf.rsonly exercisemap_legacy_err(the initial-request path). The mid-stream body-error path handled bymap_hyper_err— the other half of this file's contract — isn't exercised by any provided test.Consider adding a test that has the server send a partial/chunked response then abruptly close the connection mid-body, verifying the streamed body yields
HttpError::Other.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/adapter/net/http/hyper/src/error.rs` around lines 24 - 30, Add test coverage for the mid-stream body-error path handled by map_hyper_err in error.rs, since only map_legacy_err is currently exercised by the existing leaf.rs tests. Extend the relevant HTTP client/server test setup in leaf.rs to return a partial/chunked response and then abruptly close the connection while the body is still streaming, and assert that reading the streamed body produces HttpError::Other. Use the existing map_hyper_err and HttpError::other contract as the target behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/adapter/net/http/hyper/src/error.rs`:
- Around line 24-30: Add test coverage for the mid-stream body-error path
handled by map_hyper_err in error.rs, since only map_legacy_err is currently
exercised by the existing leaf.rs tests. Extend the relevant HTTP client/server
test setup in leaf.rs to return a partial/chunked response and then abruptly
close the connection while the body is still streaming, and assert that reading
the streamed body produces HttpError::Other. Use the existing map_hyper_err and
HttpError::other contract as the target behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 57456814-ab6c-4a0a-8d35-574c3e0fe75e
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock,!**/*.lock
📒 Files selected for processing (12)
CHANGELOG.mdCargo.tomlcrates/adapter/net/http/hyper/Cargo.tomlcrates/adapter/net/http/hyper/src/build.rscrates/adapter/net/http/hyper/src/error.rscrates/adapter/net/http/hyper/src/leaf.rscrates/adapter/net/http/hyper/src/lib.rscrates/adapter/net/http/hyper/src/timer.rsdeny.tomldocs/adr/0030-http-transport-contract-wire-bytes-streaming-composition.mddocs/superpowers/plans/2026-07-05-net-http-hyper-backend-pr-a.mddocs/superpowers/specs/2026-07-05-net-http-hyper-backend-design.md
Addresses a CodeRabbit review nitpick on #90: the streaming body-error mapper had no test; only the send-phase mapper (map_legacy_err) did. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes #89
PR A (transport) of the net-http hyper-backend slice — the runtime/TLS half deferred by the
stack()assembly (#88). Design:docs/superpowers/specs/2026-07-05-net-http-hyper-backend-design.md; plan:docs/superpowers/plans/2026-07-05-net-http-hyper-backend-pr-a.md.New crate
oath-adapter-net-http-hyper— the first (and only) crate to ownhyper/tokio/rustls(ADR-0030 §7's containment boundary). Behind theHttpClientseam, so a futurenet-http-reqwestis zero churn to the stack.TokioTimer— the tokio-backedTimer(sleep+nowboth on tokio's clock, so it stays coherent understart_paused).HyperLeaf/hyper_leaf(conn)/ConnConfig— a pooledhyper_utillegacy::Clienton a rustls HTTPS connector (aws-lc-rs provider, webpki-roots, ALPNh2+http/1.1,TCP_NODELAY).ConnConfig={ pool_max_idle_per_host, pool_idle_timeout, connect_timeout };connect_timeoutis a distinct, tighter bound than the per-attemptTimeoutlayer. The blanket impl (ADR-0030 §6) makesHyperLeaf: HttpClientonce its body error is normalized.HyperBody = MapErr<Incoming, fn(hyper::Error) -> HttpError>+ themap_legacy_err/map_hyper_erranti-corruption mappers: connect-phase (DNS/TCP/TLS/handshake, incl. connect-timeout) →HttpError::Connection; everything else + mid-stream body errors →HttpError::Other. NoTimeoutmapping (that's the layer's job).build<T, A, K>(…) = stack(hyper_leaf(conn), …)— a one-line delegation to the feat(net): stack() assembly + HttpConfig (Slice 2) #88 assembly, so the ordering invariants stay tested there. Returnimpl HttpClient + Clone + Send + Sync + 'static.Response bodies stream (
ResponseBody::streaming); leaf-side buffering (BufferMode) follows in PR B.Guarded(the concurrency permit) is attached by theRateLimitlayer, not the leaf.Tests (deterministic, no external network): plain-HTTP loopback round-trip; a real self-signed TLS handshake (rcgen cert + a client trusting exactly that cert — exercises aws-lc-rs/webpki in CI); connect-timeout →
Connection; aborted connection →Other; deterministic paused-timeTokioTimertest; and abuild()smoke that round-trips through the full stack plus a missing-coverage →BuildError::UndeclaredKeyboot-check.just ci+just msrvgreen. One narrow, documenteddeny.tomllicense exception (webpki-roots→ CDLA-Permissive-2.0, Mozilla's CA-bundle data license — first surfaced now that cargo-deny walks the hyper/rustls tree).🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation