Phase 7b: user-supplied middleware, client interceptors, Beast graceful drain - #16
Merged
Merged
Conversation
…se 7 Client interceptor chain + server RequestHandler middleware as the extension seams the logging/metrics and auth work should build on. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
The middleware seams recorded in the PLAN, plus server-robustness work:
- runtime //runtime:server gains user-supplied middleware:
Middleware = function<RequestHandler(RequestHandler)>, Chain()
composing first-outermost around the handler a generated server
exposes (works with any transport, no codegen involved), and
Observe() — the structured-logging/metrics hook reporting
{method, target, status, duration} per request with an injectable
clock.
- runtime //runtime:client gains Interceptor hooks around every HTTP
attempt a generated client makes: ModifyBeforeTransmit mutates a
fresh per-attempt copy of the request (auth headers, tracing ids;
edits never accumulate across retries), ReadAfterTransmit observes
the outcome. Registered on ClientConfig::interceptors, run in order
inside SendWithRetries; generated clients pass them through. A
weather e2e test drives a bearer-token interceptor against an
auth-checking middleware chain over generated code.
- BeastServerTransport: Stop() now drains — the acceptor closes
immediately (posted onto its strand), keep-alive reads cease, and
in-flight requests get drain_timeout_seconds (default 10) to finish
writing before the pool is torn down; new max_header_bytes option
caps request headers alongside the existing body limit.
- docs: production guide sections for interceptors, middleware, and
the hardened server transport; server guide, runtime overview, and
README updates.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second Phase 7 hardening slice: the user-supplied middleware seams (recorded in the PLAN per review feedback), client interceptors, and server-transport robustness.
Server middleware (
//runtime:server)smithy::server::Middleware(function<RequestHandler(RequestHandler)>) andChain(), composing first-outermost around the plainRequestHandlerevery generated server already exposes — auth checks, logging, metrics wrap outside the generated router and work with any transport; no codegen involved.Observe()— the built-in structured-logging/metrics hook: one callback per served request with{method, target, status, duration}and an injectable clock for deterministic tests.Client interceptors (
//runtime:client)smithy::Interceptorhooks around every HTTP attempt a generated client makes:ModifyBeforeTransmit(request, attempt)mutates a fresh per-attempt copy (auth headers, tracing ids — edits never accumulate across retries or leak into the caller's request),ReadAfterTransmit(request, outcome, attempt)observes.ClientConfig::interceptors, run in registration order insideSendWithRetries; generated clients pass them through (goldens regenerated).Beast server robustness
Stop()closes the acceptor immediately (posted onto its strand), keep-alive reads cease, and requests already read off the wire getdrain_timeout_seconds(default 10) to finish writing before the thread pool is torn down. New test stops the server mid-handler and asserts the response still arrives intact.max_header_bytesoption (default 8 KiB) caps request headers alongside the existing body limit, with a rejection test.Docs
Production guide gains interceptor and middleware sections with worked examples plus the hardened-transport summary; server guide, runtime overview, and README updated. Also carries the PLAN entry recording user-supplied middleware as a Phase 7 deliverable.
Validation
bazel test //...— 44/44 green locally, plus ASan+UBSan (Beast targets are CI-verified: boost sources aren't fetchable in the local sandbox)🤖 Generated with Claude Code
https://claude.ai/code/session_01WjaNFwBZxoHdqagvq8ycQf
Generated by Claude Code