56 lines
2.1 KiB
Markdown
56 lines
2.1 KiB
Markdown
---
|
|
id: proxy/host-routing
|
|
name: Implement Host-based routing with global routing table from DynamicConfig
|
|
status: completed
|
|
depends_on: [config/dynamic-config]
|
|
scope: narrow
|
|
risk: low
|
|
impact: component
|
|
level: implementation
|
|
---
|
|
|
|
## Description
|
|
|
|
Implement the host-based routing that matches incoming requests to site definitions. Sites are defined per-listener in TOML but collected into a single global routing table in `DynamicConfig`.
|
|
|
|
### Routing Logic
|
|
|
|
1. Check for `/health` path — if matched, return 200 OK with empty body (regardless of Host)
|
|
2. Extract `Host` header from request
|
|
3. If no `Host` header, return `400 Bad Request`
|
|
4. Normalize `Host` to lowercase, strip port component (e.g., `git.alk.dev:443` → `git.alk.dev`)
|
|
5. Look up normalized host in the global routing table
|
|
6. If found, forward to the matching `SiteConfig`'s upstream
|
|
7. If not found, return `404 Not Found`
|
|
|
|
### Global Routing Table
|
|
|
|
The routing table is a `HashMap<String, SiteConfig>` (or similar) in `DynamicConfig`, built by collecting all sites from all listeners. Hostnames must be unique — validation enforces this.
|
|
|
|
The routing table is part of `DynamicConfig` and is swapped atomically on config reload. This means a config reload can add, remove, or change site routing without restarting.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] Host-based routing extracts `Host` header and normalizes to lowercase
|
|
- [ ] Port component stripped from `Host` header before matching
|
|
- [ ] `/health` path matches regardless of `Host` header, returns 200 OK
|
|
- [ ] Missing `Host` header returns `400 Bad Request`
|
|
- [ ] Unknown host returns `404 Not Found`
|
|
- [ ] Global routing table built from all listeners' site definitions
|
|
- [ ] Routing table updates atomically on config reload via ArcSwap
|
|
- [ ] Case-insensitive host matching per RFC 7230 §2.7.3
|
|
- [ ] Unit tests for host normalization (case, port stripping)
|
|
- [ ] Unit tests for routing table lookup (match, no match)
|
|
|
|
## References
|
|
|
|
- docs/architecture/proxy.md — Host-based routing section
|
|
- docs/architecture/config.md — DynamicConfig, global routing table
|
|
|
|
## Notes
|
|
|
|
> To be filled by implementation agent
|
|
|
|
## Summary
|
|
|
|
> To be filled on completion |