Skip to content

feat(elbv2): in-process HTTP data plane for ALBs#775

Merged
vieiralucas merged 2 commits intomainfrom
worktree-batch7-elbv2-dataplane
Apr 26, 2026
Merged

feat(elbv2): in-process HTTP data plane for ALBs#775
vieiralucas merged 2 commits intomainfrom
worktree-batch7-elbv2-dataplane

Conversation

@vieiralucas
Copy link
Copy Markdown
Member

@vieiralucas vieiralucas commented Apr 26, 2026

Summary

  • For each active ALB, supervisor binds a TCP listener on 127.0.0.1:0 and serves HTTP/1.1 requests through the listener-rule chain.
  • Rule matching: host-header, path-pattern, http-request-method, http-header, query-string, source-ip (IPv4 + IPv6 CIDR), with */? glob wildcards.
  • Actions: forward (weighted round-robin + AWSALB sticky cookie + X-Forwarded-* headers), fixed-response, redirect (301/302). authenticate-oidc / authenticate-cognito return 501 (next-batch item).
  • Bound port surfaced via boundPort field on GET /_fakecloud/elbv2/load-balancers. Disable with FAKECLOUD_ELBV2_DISABLE_DATAPLANE=true.
  • HTTPS termination, raw NLB TCP forward, and mTLS wiring split out as explicit next-batch items in the docs.

Test plan

  • cargo test -p fakecloud-elbv2 — 18/18 unit tests pass (router glob, CIDR, host/path/method/header conditions).
  • cargo test -p fakecloud-e2e --test elbv2_dataplane — 2/2 (forward to registered target + fixed-response 418/teapot).
  • cargo test -p fakecloud-conformance --test elbv2 — 51/51, no regressions.
  • cargo clippy --workspace --all-targets -- -D warnings clean.
  • Watch CI + Cubic on this PR.

Summary by cubic

Adds an in-process HTTP data plane for ELBv2 ALBs: each active ALB binds a localhost port and routes HTTP/1.1 requests through its listener/rule chain with forward, fixed-response, and redirect actions. Enabled by default (set FAKECLOUD_ELBV2_DISABLE_DATAPLANE=true to disable); scope is ALBs only, with HTTPS termination and NLB TCP forwarding planned next-batch.

  • New Features

    • Per-ALB TCP bind on 127.0.0.1 with the bound port exposed as boundPort on GET /_fakecloud/elbv2/load-balancers.
    • Rule conditions: host-header, path-pattern (*/?), http-request-method, http-header, query-string, source-ip (IPv4/IPv6 CIDR).
    • Actions: forward (weighted TGs, per-TG RR, skips unhealthy/unused targets, AWSALB sticky cookie, X-Forwarded-* + X-Amzn-Trace-Id), fixed-response, redirect (301/302). authenticate-oidc/authenticate-cognito return 501 for now.
  • Bug Fixes

    • Redirect preserves path/query casing; only scheme/host are lowercased.
    • Query-string condition matching is case-insensitive for keys and values.
    • X-Forwarded-Port now reflects the listener port (client-facing), not the upstream target port.

Written for commit c882fde. Summary will update on new commits.

For each ALB whose state_code is "active", the supervisor binds a TCP
listener on 127.0.0.1:0 and serves HTTP/1.1 requests through the
listener-rule chain. NLB/GWLB and HTTPS termination are explicit
next-batch items.

Routing:
- Rule conditions: host-header, path-pattern (case-sensitive globs),
  http-request-method, http-header (glob), query-string,
  source-ip (IPv4 + IPv6 CIDR).
- Rule selection: priority asc; default rules considered last; falls
  back to listener default_actions when no rule matches.

Actions:
- forward: weighted round-robin across target groups, per-TG round-
  robin across healthy targets, AWSALB sticky cookie when stickiness
  is enabled. Adds X-Forwarded-For/Proto/Port + X-Amzn-Trace-Id.
- fixed-response: returns the configured status/body/content-type.
- redirect: HTTP_301 / HTTP_302 with a Location built from the
  redirect config + request fallback.
- authenticate-oidc / authenticate-cognito: 501 (next batch).

Wiring:
- LoadBalancer state gains bound_port: Option<u16> (skipped on
  serialize — restart re-binds).
- Service::new spawns the supervisor alongside the existing prober.
- Introspection /_fakecloud/elbv2/load-balancers exposes boundPort.
- FAKECLOUD_ELBV2_DISABLE_DATAPLANE=true turns the data plane off
  for tests that only assert control-plane behavior.

Tests:
- 7 new router unit tests (glob, host/path/method/header globs, CIDR).
- 2 new E2E tests (forward to a registered target + fixed-response
  status code) using a tiny echo HTTP server as the upstream.

Docs:
- README, services/_index, services/elbv2, llms.txt updated.
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 26, 2026

Codecov Report

❌ Patch coverage is 27.17391% with 603 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/fakecloud-elbv2/src/dataplane.rs 4.31% 510 Missing ⚠️
crates/fakecloud-elbv2/src/router.rs 68.49% 92 Missing ⚠️
crates/fakecloud-server/src/introspection.rs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

4 issues found across 14 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/fakecloud-elbv2/src/router.rs">

<violation number="1" location="crates/fakecloud-elbv2/src/router.rs:76">
P2: Query-string condition matching is case-sensitive, but ALB query-string evaluation is case-insensitive.</violation>
</file>

<file name="crates/fakecloud-elbv2/src/dataplane.rs">

<violation number="1" location="crates/fakecloud-elbv2/src/dataplane.rs:426">
P1: `.to_lowercase()` on the entire redirect URL corrupts case-sensitive path and query components. Only the scheme and host are case-insensitive; the path and query must preserve their original casing.</violation>

<violation number="2" location="crates/fakecloud-elbv2/src/dataplane.rs:565">
P2: `X-Forwarded-Port` should be the listener port the client connected to, not the upstream target port. AWS ALB populates this header with the listener's port (e.g. 80, 443).</violation>
</file>

<file name="crates/fakecloud-e2e/tests/elbv2_dataplane.rs">

<violation number="1" location="crates/fakecloud-e2e/tests/elbv2_dataplane.rs:145">
P2: Wait for the target to become healthy before issuing the request. Otherwise this test can race the health checker and flake with a 503.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread crates/fakecloud-elbv2/src/dataplane.rs Outdated
Comment thread crates/fakecloud-elbv2/src/router.rs Outdated
Comment thread crates/fakecloud-elbv2/src/dataplane.rs Outdated
Comment thread crates/fakecloud-e2e/tests/elbv2_dataplane.rs
- redirect_action: only lowercase scheme + host in Location header,
  preserve original case for path/query (RFC 3986).
- router query-string: case-insensitive key + value matching to
  match AWS ALB semantics.
- forward_action: X-Forwarded-Port now reflects the listener port
  the client connected to, not the upstream target port.
- elbv2_dataplane_forwards_to_target: wait for target to reach
  `healthy` state before issuing the forward request, eliminating
  the race with the prober.
@vieiralucas vieiralucas merged commit 77cfb70 into main Apr 26, 2026
38 checks passed
@vieiralucas vieiralucas deleted the worktree-batch7-elbv2-dataplane branch April 26, 2026 07:45
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