fix(operator): strip stage prefix on private API GW integrations#1283
Conversation
Private (VPC_LINK) HTTP API integrations forward the stage-prefixed request path to the backend by default (e.g. `/prod/webhook/telegram` instead of `/webhook/telegram`), per AWS's documented behavior for private integrations. OpenAB's webhook router matches the exact configured path, so every request 404s at the container despite the VPC Link, Cloud Map, and route wiring all being otherwise correct. Found via live E2E testing against a real deployed Telegram bot: the integration, route, and Cloud Map instance all checked out correctly via the AWS API, and API Gateway access logs confirmed the route was matched and the integration invoked ($context.integrationStatus=404), but the request never reached openab's handler. Earlier scratch tests with an echo-image backend didn't catch this because that image doesn't do path-based routing. Fix: set `overwrite:path=$request.path` on the integration's request parameters when creating it, and self-heal existing integrations created before this fix by patching the parameter in on the next `oabctl apply` (no manual intervention or service recreate needed). Verified live: 404 reproduced on a fresh deploy, manually patching the parameter via the AWS CLI immediately fixed it, then re-ran two full apply/delete cycles with the fixed binary — both created the integration with the override baked in automatically and returned 200 OK end-to-end (API Gateway -> VPC Link -> Cloud Map -> Fargate).
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
LGTM ✅ — Well-diagnosed fix for a real 404 bug in private VPC_LINK integrations, with self-healing for existing deployments and thorough regression tests. No actionable blockers. What This PR DoesFixes a persistent 404 on webhook endpoints caused by API Gateway forwarding the stage-prefixed path (e.g. How It WorksSets Findings
Team Review — Concerns Raised & DispositionsThe review team raised 9 potential concerns (all 🟡). After cross-referencing AWS documentation and analyzing the codebase, none are actionable blockers for this PR:
What's Good (🟢)
Baseline Check
|
Summary
Fixes a real 404 bug in
oabctl's API Gateway ingress (#1275) found via liveE2E testing against a real deployed Telegram bot.
Private (
VPC_LINK) HTTP API integrations forward the stage-prefixedrequest path to the backend by default (e.g.
/prod/webhook/telegraminsteadof
/webhook/telegram) — this is documented AWSbehavior
for private integrations. OpenAB's webhook router (
axum) matches the exactconfigured path, so every request 404s at the container even though the VPC
Link, Cloud Map instance, route, and integration are all wired correctly.
Fix: set
overwrite:path=$request.pathon the integration's requestparameters when creating it, so the backend receives the stage-stripped path.
Existing integrations created before this fix self-heal on the next
oabctl apply— the code detects the missing parameter and patches it in viaUpdateIntegration, no manual intervention or service recreate needed.The bug, visually
Everything except the final hop — VPC Link status, Cloud Map SRV resolution,
route/integration config — was already correct and reported healthy by every
aws apigatewayv2/servicediscovery get-*call. Only the one requestparameter mapping on the integration was missing.
How this was found
Ran a full from-scratch
oabctl applyagainst a real Telegram bot deployment.The webhook URL returned a persistent
404for 20+ minutes — not a briefwarm-up delay like previously-observed
503s. Isolated the cause by:AVAILABLE, the Cloud Map instancewas
HEALTHY/discoverable, the route/integration/stage were all configuredexactly as expected via
aws apigatewayv2 get-*— everything checked out./webhook/telegramvia CloudWatch logs — no crash, no error.
showed
routeKey=POST /webhook/telegram status=404 integrationStatus=404— proving API Gateway matched the route and invoked the integration, but
the backend returned 404.
src/main.rs) confirmed exact-pathaxumrouting, and AWS's private-integration docs confirmed thestage-prefix forwarding behavior.
overwrite:path=$request.pathvia the AWS CLI fixed itimmediately (
200 OK).An earlier round of scratch testing with an echo-image backend
(
mendhak/http-https-echo) never caught this, because that image echoes backwhatever path it receives — it doesn't do path-based routing, so it can't
expose a path-mismatch bug.
Verification
cargo build --release,cargo clippy --all-targets -- -D warnings,cargo test --release— all clean on macmini (19/19 tests pass, 4 newregression tests for the extracted
has_stage_path_overridehelper).oabctl apply→ test webhook →oabctl deletecycleswith the fixed binary against a real deployed bot
(
ghcr.io/openabdev/openab:pre-beta-kiro+ real Telegram config/secret).Both cycles created the integration with the path override baked in
automatically (no manual patching) and both returned
200 OKend-to-end(curl → API Gateway → VPC Link → Cloud Map → Fargate → openab), after the
expected brief
503VPC Link warm-up window.cleaned up after each cycle; confirmed via a final sweep.
Testing done
Plus live E2E against real AWS resources in a scratch account/VPC (see
commit message for the reproduction sequence).