maksit-certs-ui/assets/docs/REVERSE_PROXY_ROUTING.md
2026-05-03 10:35:34 +02:00

66 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Reverse proxy routing (YARP)
The **`ReverseProxy`** project ([`src/ReverseProxy`](../../src/ReverseProxy)) is an **ASP.NET + YARP** edge that listens on **port 8080** in Docker Compose (`docker-compose.override.yml` maps `8080:8080`).
**Config:** [`src/ReverseProxy/appsettings.json`](../../src/ReverseProxy/appsettings.json)
**Certs routing:** **`/.well-known/acme-challenge/`** is matched **before** the SPA catch-all so HTTP-01 challenges reach the WebAPI on the **same public host** as the UI.
---
## Route table
Routes use explicit **`Order`** (lower = matched first) so the SPA catch-all never wins over `/api`, `/swagger`, or `/.well-known/` when JSON key order varies.
Compose service names are **`server`** (WebAPI) and **`client`** (Vite/WebUI). Cluster IDs **`webapiCluster`** / **`webuiCluster`** reference those upstreams.
| Order | Path match | Cluster | Upstream (Compose) |
|------|------------|---------|---------------------|
| 5 | `/.well-known/acme-challenge/{**catch-all}` | `webapiCluster` | `http://server:5000/` |
| 10 | `/swagger/{**catch-all}` | `webapiCluster` | `http://server:5000/` |
| 20 | `/api/{**catch-all}` | `webapiCluster` | `http://server:5000/` |
| 1000 | `/{**catch-all}` | `webuiCluster` | `http://client:5173/` |
YARP forwards the **same path** to the destination. Example:
- Client: `POST http://localhost:8080/api/identity/login`
- Proxied to: `POST http://server:5000/api/identity/login`
Controllers use the usual **`/api/...`** prefix (e.g. `api/identity`, account and certificate flows)—there is **no** `api/vault`-style segment. Locally, the Web UI uses `public/config.js` / `.env` with `http://localhost:8080/api` so XHR calls go **through** YARP.
### HTTP-01 (Lets Encrypt)
Traffic for **`/.well-known/acme-challenge/*`** must reach **MaksIT.CertsUI** so the HTTP-01 validator can fetch the token body from the API (backed by PostgreSQL). The dedicated route sends that path to the **`server`** service (same `webapiCluster` as `/api`).
### Kubernetes (Helm)
The chart can mount **`config.js`** from a ConfigMap (`certsClientRuntime.apiUrl`). Defaults in `values.yaml` may use a full origin (example host); you can also use a **relative** API base such as **`/api`** so the browser uses the same host and port as the page (ingress / port-forward to **8080** on the reverse-proxy Service) without hard-coding `localhost`. Use a full URL only if the UI and API are served from different origins.
---
## Automation and clients
- **Base URL** for scripts, the Agent, or any HTTP client talking to the **composed** stack should be the **proxy origin**: `http://localhost:8080` when you use Composes published port.
- **Path shape:** Call **`/api/...`** on that origin (either concatenate `BaseAddress` + `api/...` or set `VITE_API_URL` / runtime `API_URL` to `http://localhost:8080/api` so the client already includes `/api`).
- **YARP** forwards request headers to the WebAPI by default (including **`Authorization: Bearer`** for JWT). No special transform is required unless you customize YARP transforms.
---
## Direct vs proxied ports (local dev)
| Scenario | Typical base URL for Certs HTTP API |
|----------|-------------------------------------|
| Docker Compose (this repo) | `http://localhost:8080` (through YARP) |
| Run **MaksIT.CertsUI** only (F5 / `dotnet run`) | See `launchSettings.json` (e.g. `http://localhost:5016`) — **no** YARP |
| Run **ReverseProxy** only (outside Compose) | `launchSettings`: e.g. `http://localhost:5276` — cluster addresses in `appsettings.json` must resolve (Compose service names only work **inside** the Compose network) |
If authentication succeeds but API calls fail, confirm traffic reaches the **same** WebAPI instance and data volume you expect (not a different port or stale container).
---
## Related files
- [`src/docker-compose.yml`](../../src/docker-compose.yml), [`src/docker-compose.override.yml`](../../src/docker-compose.override.yml)
- [`src/ReverseProxy/Program.cs`](../../src/ReverseProxy/Program.cs)
- WebUI runtime API base: [`src/MaksIT.WebUI/public/config.js`](../../src/MaksIT.WebUI/public/config.js), Helm `certsClientRuntime.apiUrl` in [`src/helm/values.yaml`](../../src/helm/values.yaml)