Skip to content

refactor(middleware)!: adopt two-mode HTTP body protocol - #3450

Open
pimlock wants to merge 3 commits into
mainfrom
feat/2431-streaming-request-middleware/pimlock
Open

pimlock wants to merge 3 commits into
mainfrom
feat/2431-streaming-request-middleware/pimlock

Conversation

@pimlock

@pimlock pimlock commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replace the WIP HTTP middleware body protocol with the approved two-mode, fail-closed contract. Request middleware now selects bounded in-memory BUFFERED processing or independent duplex STREAM processing, while response middleware initially offers BUFFERED only. OpenShell does not retain STREAM recovery copies or spool middleware bodies to disk.

This is the base protocol/runtime PR in a three-PR stack:

  1. This PR: HTTP middleware hook, protocol, runtime, content-guard migration, and documentation.
  2. Follow-up stacked on this PR: move AWS SigV4 into a trusted built-in middleware.
  3. Follow-up stacked on the SigV4 PR: add Git signing as a separate built-in middleware.

The existing inline proxy SigV4 implementation remains in this base PR. Git signing is intentionally excluded.

Related Issue

Part of #2431

Closes #3307

Follow-up to #2426 and #3074.

Changes

  • Add phase-specific EvaluateHttp(stream HttpEvent) returns (stream HttpResult) services with explicit HTTP protocol-version and body-mode capability negotiation.
  • Reduce HTTP body handling to BUFFERED and STREAM; remove ownership acknowledgements, sequence/ACK/replay state, skip semantics, and proxy-managed middleware spooling.
  • Run STREAM input and output as independent bounded pumps so middleware can emit early output or delay OutputStart until it has consumed the full request.
  • Keep BUFFERED bodies bounded in RAM with explicit unchanged/replacement results.
  • Make HTTP middleware failures fail closed, including over-capacity bodies and external transport/protocol errors; retain WebSocket-only fail-open behavior.
  • Preserve protected-header handling, body-aware protocol inspection, response eligibility rules, trailer/framing validation, cancellation, deadlines, and policy-generation checks.
  • Offer BUFFERED-only response processing in this rollout and apply the response whole-body deadline across both collection and middleware completion.
  • Remove the unused public POST_CREDENTIALS phase and reserve its enum value for wire safety.
  • Migrate the content-guard example and update architecture, RFC, published documentation, gateway-config reference, and related public skills.

Design artifacts

Testing

  • mise run pre-commit
  • mise run test
  • mise run ci
  • Middleware and network focused tests, including delayed whole-body STREAM output, early streaming output, fail-closed over-capacity handling, normalized external diagnostics, response deadlines, invalid event ordering, and chain behavior
  • mise run e2e exercised the relevant proxy paths; its aggregate run later hit shared Docker runtime contention in provider_readiness, which passed when rerun in isolation with OPENSHELL_E2E_DOCKER_TEST=provider_readiness mise run e2e:rust

The first final mise run ci attempt hit a timing-sensitive plaintext MCP proxy test under maximum parallel load. That test passed in isolation, in mise run test, and in the successful full CI rerun.

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture and user-facing documentation updated
  • Public protobuf compatibility and mixed-version failure behavior reviewed
  • Related skills reviewed and synchronized

Replace the unary HTTP request evaluator with a bidirectional streaming protocol and move SigV4 signing into the built-in middleware stage.

BREAKING CHANGE: replace the unary HTTP request middleware RPC with the streaming HttpRequestPreCredentials Evaluate contract.

Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
@github-actions

Copy link
Copy Markdown

@sylvesterkaczmarek sylvesterkaczmarek left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In auto mode, a bodyless request with no x-amz-content-sha256 falls through to UNSIGNED-PAYLOAD. That's not the normal SigV4 empty-body hash and is service-specific, so a GET/HEAD to a non-S3 AWS service can be re-signed with payload semantics the service rejects. Could BodyFraming::None sign Bytes(&[]) unless the client explicitly requested an unsigned payload, and add a non-S3 empty-body case?

@pimlock
pimlock marked this pull request as draft September 18, 2026 16:48
@copy-pr-bot

copy-pr-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
@pimlock pimlock changed the title feat(middleware)!: add streaming request hooks refactor(middleware)!: adopt two-mode HTTP body protocol Sep 19, 2026
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
@pimlock

pimlock commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test 96ff945

@pimlock
pimlock marked this pull request as ready for review September 19, 2026 06:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(middleware)!: replace unary HTTP request evaluation with a streaming hook

2 participants