Skip to content

fix(proxy): make ampcode passthrough fully transparent#90

Open
AprilNEA wants to merge 2 commits into
masterfrom
fix/amp-transparent-passthrough
Open

fix(proxy): make ampcode passthrough fully transparent#90
AprilNEA wants to merge 2 commits into
masterfrom
fix/amp-transparent-passthrough

Conversation

@AprilNEA
Copy link
Copy Markdown
Owner

Summary

  • /api/* and /v0/management/* now forward amp CLI traffic verbatim — only hop-by-hop headers + host are stripped (RFC 7230). byokey no longer overwrites Authorization / X-Api-Key or injects its own amp token for these non-AI endpoints.
  • Response body is streamed back via Body::from_stream(resp.bytes_stream()) instead of buffered with resp.bytes().await, so SSE turn-continuation (which fires after the read tool returns a file) reaches the client in real time.
  • /api/provider/* is unchanged — byokey still owns AI traffic and its per-provider handlers build their own auth.
  • forward_headers_middleware and its ForwardedHeaders extension are deleted; no remaining handler reads them.

Why

The amp CLI's read tool reads a local file and POSTs the result back to a thread endpoint under /api/*. Before this change, byokey rewrote the request auth (causing thread ops to run as the wrong principal when byokey held an amp token) and held the streaming reply in memory until upstream closed. Net effect: the read tool appeared to hang or never continue the AI turn. See also the recent investigation captured in docs/dia-browser-interception.md / the attached thread.

Test plan

  • cargo check -p byokey-proxy — clean
  • cargo test -p byokey-proxy --lib — 47 passed, 0 failed (including test_amp_login_redirect, test_amp_cli_login_redirect)
  • cargo clippy -p byokey-proxy --all-targets — clean
  • Manual: run amp CLI with a prompt that triggers the read tool and confirm the AI turn continues after the file is read
  • Manual: confirm amp login / thread list still works (headers go through untouched now)

Follow-up

config.amp.upstream_key is now a dead config field — only the deleted middleware read it. Happy to rip it out in a separate PR if desired.

The /api/* and /v0/management/* catch-all proxy was rewriting the amp
CLI's own headers (stripping Authorization/X-Api-Key, injecting byokey's
amp token) and buffering the entire upstream response before returning
it. Both broke the amp `read` tool: the rewritten auth caused thread
operations to run as the wrong principal, and buffering prevented the
SSE turn-continuation from streaming back to the client.

Forward the amp CLI's request verbatim (only hop-by-hop + host stripped
per RFC 7230) and stream the response body back. /api/provider/* is
unaffected — byokey still owns AI traffic. The forward_headers
middleware is deleted since no other route needed it.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f63520c961

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +573 to +577
let mut fwd = rquest::header::HeaderMap::new();
for (name, value) in &headers {
let name_str = name.as_str();
if HOP_BY_HOP.contains(&name_str) || name_str == "host" {
continue;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Restore shared-proxy auth injection for amp passthrough

This change makes /api/* and /v0/management/* fully pass through client headers, but it also removes the only runtime use of amp.upstream_key (documented in crates/config/src/schema/amp.rs as enabling shared-proxy mode). In deployments that rely on that setting, requests that previously worked with injected proxy credentials will now be sent with missing or client-scoped auth and start failing with upstream 401/403. If shared-proxy mode is being deprecated, this commit should fail fast when amp.upstream_key is set instead of silently ignoring it.

Useful? React with 👍 / 👎.

rquest is built with `features = ["full"]` so it auto-decompresses
gzip/brotli/zstd response bodies before `bytes_stream()` yields them.
The prior passthrough still forwarded upstream's `Content-Encoding`
and `Content-Length` headers, which described the *compressed*
payload — so the amp CLI saw `Content-Encoding: gzip` and tried to
decode already-decoded bytes, got garbage, silently failed, and fell
back to a degraded mode policy where `read`/`bash` aren't allowed
in smart mode.

Strip both headers on the catch-all response path so axum sends the
decompressed body as chunked without a misleading encoding hint.
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.

1 participant