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

**Related:** The same topic in **MaksIT-Vault** is documented at [`REVERSE_PROXY_ROUTING.md`](../../maksit-vault/assets/docs/REVERSE_PROXY_ROUTING.md) when both repos sit side by side; otherwise open that path in your Vault clone. Vault’s table does **not** include an **ACME HTTP-01** path—Certs adds **`/.well-known/acme-challenge/`** so challenges hit the WebAPI on the **same public host** as the UI.

---

## Route table

Routes use explicit **`Order`** (lower = matched first), matching **MaksIT-Vault**, 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`** match Vault for a parallel mental model.

| 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 (Let’s Encrypt)

Traffic for **`/.well-known/acme-challenge/*`** must reach **MaksIT.Webapi** so the HTTP-01 validator can fetch the token file. 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 Compose’s 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.Webapi** 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)
