Skip to content

Typed request/response custom headers - #15

Open
aloks98 wants to merge 9 commits into
feat/l4from
feat/custom-headers
Open

Typed request/response custom headers#15
aloks98 wants to merge 9 commits into
feat/l4from
feat/custom-headers

Conversation

@aloks98

@aloks98 aloks98 commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Adds both-direction custom headers to reverse proxies — request headers sent to the upstream and response headers returned to the client. Previously custom_headers were applied only as request headers (surfaced by the traffic E2E suite in the base PR).

Stacked on #14 (feat/l4). Review/merge #14 first; this PR's base is feat/l4.

What changed

  • Model (CustomHeaders type): flexible UnmarshalJSON accepts both the legacy flat map (→ request headers) and the nested {"request":{...},"response":{...}} shape; normalizes to nested on read; GORM Scan/Value so legacy rows load transparently — no DB migration.
  • Builder: applies request headers to Headers.Request (layered on standard proxy headers) and response headers to Headers.Response.
  • API: no DTO change needed (handler embeds models.Proxy); responses return the normalized nested shape.
  • UI: nested CustomHeaders type + two key-value editors in the reverse-proxy form ("Request headers to upstream" / "Response headers to client") + fixed the change-detection comparison.
  • Tests: model unit tests (flat/nested/response-only/round-trip), builder unit tests (both directions), and the traffic E2E custom_headers scenario un-skipped — asserts a response header reaches the client AND a request header reaches the backend.
  • Docs (API_PROXY, curl examples, test script, schema comment) updated to the nested shape.

Backward compatibility

A flat custom_headers map (existing DB rows and old API clients) keeps working as request headers. Empty serializes as {} (accepted per design).

Known follow-up (pre-existing, not in this PR)

custom_headers changes aren't recorded in the proxy audit log (the old flat headers weren't either).

Test plan

  • go test ./backend/internal/models/ ./backend/internal/caddy/config/ -count=1 — green
  • make test-trafficcustom_headers passes both directions (no skip)
  • pnpm --dir ui build + make lint-ui — green

🤖 Generated with Claude Code

aloks98 and others added 9 commits June 7, 2026 14:06
Replace the legacy flat map iteration with the typed CustomHeaders fields:
request headers land on Headers.Request (on top of the standard proxy
headers) and response headers on Headers.Response. Also fix the remaining
Task 1 callers that used the old JSONField/nil shape so the backend builds.

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>
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