
Leichter HTTP(S)-Edge-Server und Reverse-Proxy mit automatischem SSL, Docker/Consul-Erkennung, routenspezifischer Authentifizierung, Ratenbegrenzung und gesundheitscheckbasiertem Failover.
<div align="center">
<img class="logo" src="https://raw.githubusercontent.com/umputun/reproxy/master/site/logo-bg.svg" width="355px" height="142px" alt="Reproxy | Simple Reverse Proxy"/>
</div>
Reproxy ist ein einfacher Edge-HTTP(s)-Server / Reverse-Proxy, der verschiedene Provider unterstützt (docker, static, file, consul catalog). Ein oder mehrere Provider liefern Informationen über den angeforderten Server, die angeforderte URL, die Ziel-URL und die Health-Check-URL. Es wird als einzelne Binärdatei oder als Docker-Container verteilt.
- Automatische SSL-Terminierung mit <a href="https://letsencrypt.org/" rel="nofollow noopener noreferrer" target="_blank">Let's Encrypt</a>
- Unterstützung benutzerdefinierter SSL-Zertifikate
- Einfache, aber flexible Proxy-Regeln
- Statischer Proxy-Regel-Provider über die Kommandozeile
- Dynamischer, dateibasierter Proxy-Regel-Provider
- Docker-Provider mit automatischer Erkennung
- Consul-Catalog-Provider mit Erkennung über Service-Tags
- Unterstützung mehrerer (virtueller) Hosts
- Optionale Traffic-Komprimierung
- Optionale IP-basierte Zugriffskontrolle
- Grundlegende Authentifizierung pro Route
- Benutzerdefinierte Größenbeschränkungen und Timeouts
- Verteilung als einzelne Binärdatei
- Verteilung als Docker-Container
- Integrierter Server für statische Assets mit optionalem „SPA-freundlichem" Modus
- Unterstützung von Weiterleitungsregeln
- Optionaler Limiter für die Gesamtaktivität sowie für die Aktivität einzelner Benutzer
- Live-Health-Check und Failover/Load-Balancing
- Verwaltungsserver mit Routeninformationen und Prometheus-Metriken
- Plugin-Unterstützung über RPC zur Implementierung benutzerdefinierter Funktionalität
- Optionales Logging sowohl im Apache-Log-Format als auch mit vereinfachten stdout-Berichten.
---
<div align="center">
[](https://github.com/umputun/reproxy/actions/workflows/ci.yml) [](https://coveralls.io/github/umputun/reproxy?branch=master) [](https://goreportcard.com/report/github.com/umputun/reproxy) [](https://hub.docker.com/r/umputun/reproxy)
</div>
Der Server (Host) kann als FQDN, z. B. `s.example.com`, als `*` (Catch-all) oder als Regex festgelegt werden. Exakte Übereinstimmungen haben Vorrang. Wenn es also zwei Regeln mit den Servern `example.com` und `example\.(com|org)` gibt, wird eine Anfrage an `example.com/some/url` mit der ersteren übereinstimmen. Die angeforderte URL kann ein Regex sein, zum Beispiel `^/api/(.*)`, und die Ziel-URL kann durch Regex übereinstimmende Gruppen enthalten, z. B. `http://d.example.com:8080/$1`. Für das obige Beispiel wird `http://s.example.com/api/something?foo=bar` an `http://d.example.com:8080/something?foo=bar` weitergeleitet.
Der Einfachheit halber werden Anfragen mit abschließendem `/` und ohne Regex-Gruppen zu `/(.*)` erweitert, und Ziele in diesen Fällen zu `/$1`. D. h. `/api/` -> `http://127.0.0.1/service` wird zu `^/api/(.*)` -> `http://127.0.0.1/service/$1` übersetzt.
Die Host-Substitution wird in der Ziel-URL unterstützt. Zum Beispiel wird `/files/${host}` durch den übereinstimmenden Hostnamen ersetzt. `$host` (ohne geschweifte Klammern) kann ebenfalls verwendet werden.
Sowohl HTTP als auch HTTPS werden unterstützt. Für HTTPS kann sowohl ein statisches Zertifikat als auch automatische ACME-Zertifikate (Let's Encrypt) verwendet werden. Ein optionaler Assets-Server kann zum Ausliefern statischer Dateien verwendet werden. Der Start von reproxy erfordert mindestens einen definierten Provider. Die übrigen Parameter sind streng optional und haben sinnvolle Standardwerte.
Beispiele:
- mit einem statischen Provider: `reproxy --static.enabled --static.rule="*,example.com/api/(.*),https://api.example.com/$1"`
- mit automatischer Docker-Erkennung: `reproxy --docker.enabled --docker.auto`
- als Docker-Container: `docker up -p 80:8080 umputun/reproxy --docker.enabled --docker.auto`
- mit automatischem SSL: `docker up -p 80:8080 -p 443:8443 umputun/reproxy --docker.enabled --docker.auto --ssl.type=auto --ssl.fqdn=example.com`
## Installation
Reproxy wird als kleine eigenständige Binärdatei sowie als Docker-Image vertrieben. Sowohl die Binärdatei als auch das Image unterstützen mehrere Architekturen und mehrere Betriebssysteme, darunter linux_x86_64, linux_arm64, linux_arm, macos_x86_64, macos_arm64, windows_x86_64 und windows_arm. Wir stellen außerdem sowohl arm64- als auch x86-deb- und rpm-Pakete bereit.
- für eine Binärverteilung laden Sie die passende Datei im [Release-Bereich](https://github.com/umputun/reproxy/releases) herunter
- für Homebrew-Nutzer: `brew install umputun/apps/reproxy`
- Docker-Container verfügbar auf [Docker Hub](https://hub.docker.com/r/umputun/reproxy) sowie in der [Github Container Registry](https://github.com/users/umputun/packages/container/reproxy/versions). D. h. `docker pull umputun/reproxy` oder `docker pull ghcr.io/umputun/reproxy`.
Die neueste stabile Version hat das Docker-Tag `:vX.Y.Z` (mit dem Alias `:latest`) und der aktuelle Master hat das Tag `:master`.
## Provider
Proxy-Regeln werden von verschiedenen Providern bereitgestellt. Derzeit enthalten – `file`, `docker`, `static` und `consul-catalog`. Jeder Provider kann mehrere Routing-Regeln sowohl für proxied Requests als auch für statische (Assets) definieren. Der Benutzer kann mehrere Provider gleichzeitig festlegen.
_Beispiele für verschiedene Provider finden Sie unter [examples](https://github.com/umputun/reproxy/tree/master/examples)_
### Static-Provider
Dies ist der einfachste Provider, der alle Mapping-Regeln direkt in der Befehlszeile (oder Umgebung) definiert. Mehrere Regeln werden unterstützt. Jede Regel besteht aus 3 bis 7 durch Kommas getrennten Elementen `server,sourceurl,destination[,ping-url[,forward-health-checks[,timeout[,throttle]]]]`. Zum Beispiel:
- `*,^/api/(.*),https://api.example.com/$1` – leitet alle Anfragen an einen beliebigen Host/Server mit dem Präfix `/api` an `https://api.example.com` weiter
- `example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping` – leitet alle Anfragen an `example.com` und mit der URL `/foo/bar` an `https://api.example.com/zzz` weiter und verwendet `https://api.example.com/ping` für den Health-Check.
- `example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping,true` – wie oben, leitet aber zusätzlich `/ping`- und `/health`-Anfragen an das Backend weiter.
- `example.com,^/upload/(.*),https://api.example.com/$1,,,5m` – routenspezifisches Request-Timeout von 5 Minuten (4. und 5. Feld leer gelassen, um ping-url und forward-health-checks zu überspringen).
- `example.com,^/login,https://api.example.com/login,,,,2` – routenspezifische Drosselung von 2 Anfragen/Sekunde pro Benutzer (die davorliegenden Positionsfelder bleiben leer).
Das 4. Element definiert eine optionale Ping-URL, die für die Health-Berichterstattung verwendet wird. Das 5. Element aktiviert optional die Weiterleitung von Health-Check-Anfragen an das Backend (`true`, `yes`, `1`). Weitere Details finden Sie im Abschnitt [Health check](#ping-and-health-checks). Das 6. Element ist ein optionales routenspezifisches Request-Timeout (Go-Duration, z. B. `5m`, `30s`); `0` oder leer erbt die globale Einstellung `--timeout.write`. Das 7. Element ist ein optionales routenspezifisches Limit von Anfragen/Sekunde pro Benutzer; `0` oder leer erbt `--throttle.user`. Leere Positionsfelder sind zulässig (z. B. `,,` für die ungenutzten mittleren Felder).
### File-Provider
Dieser Provider verwendet eine YAML-Datei mit Routing-Regeln.
`reproxy --file.enabled --file.name=config.yml`
Beispiel für `config.yml`:
```yaml
default: # the same as * (catch-all) server
- { route: "^/api/svc1/(.*)", dest: "http://127.0.0.1:8080/blah1/$1" }
- {
route: "/api/svc3/xyz",
dest: "http://127.0.0.3:8080/blah3/xyz",
ping: "http://127.0.0.3:8080/ping",
remote: "192.168.1.0/24, 127.0.0.1", # optional, restrict access to the route
forward-health-checks: true # optional, forward /ping and /health to backend
}
- {
route: "^/admin/(.*)",
dest: "http://127.0.0.4:8080/$1",
auth: "admin:$2y$05$..." # optional, per-route basic auth (htpasswd bcrypt format)
}
- {
route: "^/upload/(.*)",
dest: "http://127.0.0.5:8080/$1",
timeout: 5m # optional, per-route request timeout (Go duration). 0 or omitted inherits --timeout.write
}
- {
route: "^/login",
dest: "http://127.0.0.6:8080/login",
throttle: 2 # optional, per-route req/sec per user. 0 or omitted inherits --throttle.user
}
srv.example.com:
- { route: "^/api/svc2/(.*)", dest: "http://127.0.0.2:8080/blah2/$1/abc" }
- { route: "/web/", dest: "/var/www", "assets": true }
"*.files.example.com":
- { route: "^/files/(.*)", dest: "http://123.123.200.200:8080/$host/$1" }
```
Dies ist ein dynamischer Provider, und Dateiänderungen werden automatisch übernommen.
**Mehrere statische Sites auf verschiedenen Domains** können bereitgestellt werden, indem Servernamen als Schlüssel mit `assets: true` verwendet werden:
```yaml
site-en.example.com:
- { route: "/", dest: "/var/www/en", "assets": true }
site-ru.example.com:
- { route: "/", dest: "/var/www/ru", "assets": true }
```
**Wichtig:** Das Feld `route` für Asset-Regeln muss ein Pfad-Präfix sein (z. B. `/`, `/web/`), kein Regex. Regex-Muster wie `^/(.*)` funktionieren nicht mit `assets: true`, da der Abgleich statischer Assets einen Pfad-Präfix-Vergleich verwendet, keinen Regex.
### Docker-Provider
Der Docker-Provider unterstützt eine vollautomatische Erkennung (mit `--docker.auto`), ohne dass eine zusätzliche Konfiguration erforderlich ist. Standardmäßig leitet er alle Anfragen wie `http://<url>/<container name>/(.*)` an die interne IP des jeweiligen Containers und den exponierten Port weiter. Nur aktive (laufende) Container werden erkannt.
Dieser Standard kann über Labels geändert werden:
- `reproxy.server` – Server (Hostname), der übereinstimmen soll. Kann auch eine Liste von kommagetrennten Servern sein.
- `reproxy.route` – Quell-Route (Location)
- `reproxy.dest` – Zielpfad. Hinweis: Dies ist keine vollständige URL, sondern nur der Pfad, der an ip:port des Containers angehängt wird
- `reproxy.port` – Zielport für den erkannten Container
- `reproxy.ping` – Ping-Pfad für den Ziel-Container.
- `reproxy.remote` – Zugriff auf die Route mit einer Liste von kommagetrennten Subnetzen oder IPs einschränken
- `reproxy.auth` – Basic Auth für die Route mit kommagetrennten `user:bcrypt_hash`-Paaren erfordern (generiert durch `htpasswd -nbB`)
- `reproxy.assets` – Asset-Mapping als `web-root:location` festlegen, zum Beispiel `reproxy.assets=/web:/var/www`
- `reproxy.keep-host` – Host-Header unverändert lassen (`yes`, `true`, `1`) oder durch den Ziel-Host ersetzen (`no`, `false`, `0`)
- `reproxy.forward-health-checks` – `/ping`- und `/health`-Anfragen an das Backend weiterleiten, statt sie von reproxy behandeln zu lassen (`yes`, `true`, `1`). Nützlich, wenn das Backend eigene Health-Check-Endpunkte mit anwendungsspezifischen Antworten hat.
- `reproxy.timeout` – Request-Timeout pro Route als Go-Duration (z. B. `5m`, `30s`). `0` oder nicht gesetzt übernimmt das globale `--timeout.write`. Ungültige Werte werden mit einer Warnung ignoriert.
- `reproxy.throttle` – Anfragen/Sek.-Limit pro Benutzer pro Route. `0` oder nicht gesetzt übernimmt `--throttle.user`. Ungültige oder negative Werte werden mit einer Warnung ignoriert.
- `reproxy.enabled` – Container als reproxy-Ziel aktivieren (`yes`, `true`, `1`) oder deaktivieren (`no`, `false`, `0`).
Bitte beachten: Ohne `--docker.auto` muss der Ziel-Container mindestens eines der `reproxy.*`-Labels haben, um als potenzielles Ziel berücksichtigt zu werden.
Mit `--docker.auto` werden alle Container mit exponiertem Port als Routing-Ziele berücksichtigt. Es gibt 3 Möglichkeiten, dies einzuschränken:
- Bestimmte Container explizit ausschließen mit `--docker.exclude`, d. h. `--docker.exclude=c1 --docker.exclude=c2 ...`
- Nur ein bestimmtes Docker-Netzwerk zulassen mit `--docker.network`
- Das Label `reproxy.enabled=false` oder `reproxy.enabled=no` oder `reproxy.enabled=0` setzen
Wenn keine `reproxy.route` definiert ist, lautet die Standard-Route `^/<container_name>/(.*)`. Falls alle proxied Quellen dasselbe Präfix-Muster haben sollen, zum Beispiel `/api/(.*)`, kann der Benutzer das gemeinsame Präfix (in diesem Fall `/api`) für alle containerbasierten Routen definieren. Dies kann mit dem Parameter `--docker.prefix` erfolgen.
Der Docker-Provider erlaubt außerdem die Definition mehrerer Sätze von `reproxy.N.something`-Labels, um mehrere unterschiedliche Routen auf demselben Container abzubilden. Dies ist nützlich, da ein einzelner Container in manchen Fällen mehrere Endpunkte exponieren kann, zum Beispiel eine öffentliche API und eine Admin-API. Alle oben genannten Labels können mit „N-Index“ verwendet werden, d. h. `reproxy.1.server`, `reproxy.1.port` und so weiter. N sollte im Bereich 0 bis 9 liegen.
Dies ist ein dynamischer Provider, und jede Änderung des Container-Status wird automatisch übernommen.
### Consul-Catalog-Provider
Verwendung: `reproxy --consul-catalog.enabled`
Der Consul-Catalog-Provider ruft die Consul-API regelmäßig auf (standardmäßig jede Sekunde), um Dienste abzurufen, die ein Tag mit dem Präfix `reproxy.` haben. Der Benutzer kann das Prüfintervall mit dem Kommandozeilen-Flag `--consul-catalog.interval` sowie die Consul-Adresse mit der Kommandozeilen-Option `--consul-catalog.address` neu definieren. Die Standardadresse ist `http://127.0.0.1:8500`.
Zum Beispiel:
```
reproxy --consul-catalog.enabled --consul-catalog.address=http://192.168.1.100:8500 --consul-catalog.interval=10s
```
Standardmäßig legt der Provider Werte für jeden Dienst fest:
- enabled `false`
- server `*`
- route `^/(.*)`
- dest `http://<SERVICE_ADDRESS_FROM_CONSUL>/$1`
- ping `http://<SERVICE_ADDRESS_FROM_CONSUL>/ping`
Dieser Standard kann mit Tags geändert werden:
- `reproxy.server` – abzugleichender Server (Hostname). Kann auch eine Liste von kommagetrennten Servern sein.
- `reproxy.route` – Quellroute (Location)
- `reproxy.dest` – Zielpfad. Hinweis: Dies ist keine vollständige URL, sondern nur der Pfad, der an ip:port des Dienstes angehängt wird
- `reproxy.port` – Zielport für den erkannten Dienst
- `reproxy.remote` – beschränkt den Zugriff auf die Route mit einer Liste von kommagetrennten Subnetzen oder IPs
- `reproxy.auth` – erfordert Basic Auth für die Route mit kommagetrennten `user:bcrypt_hash`-Paaren (erzeugt durch `htpasswd -nbB`)
- `reproxy.ping` – Ping-Pfad für den Zieldienst.
- `reproxy.forward-health-checks` – leitet `/ping`- und `/health`-Anfragen an das Backend weiter (`true`, `yes`, `1`).
- `reproxy.timeout` – Request-Timeout pro Route als Go-Duration (z. B. `5m`, `30s`). `0` oder nicht gesetzt erbt das globale `--timeout.write`. Ungültige Werte werden mit einer Warnung ignoriert.
- `reproxy.throttle` – Anfragen/Sek.-Limit pro Benutzer pro Route. `0` oder nicht gesetzt erbt `--throttle.user`. Ungültige oder negative Werte werden mit einer Warnung ignoriert.
- `reproxy.enabled` – aktiviert (`yes`, `true`, `1`) oder deaktiviert (`any different value`) den Dienst für reproxy-Ziele.
### Compose-spezifische Details
Falls Regeln als Teil einer Docker-Compose-Umgebung gesetzt werden, kollidiert das Ziel mit der Regex-Gruppe mit der Compose-Syntax. Das heißt, der Versuch, `https://api.example.com/$1` in einer Compose-Umgebung zu verwenden, schlägt aufgrund eines Syntaxfehlers fehl. Die Standardlösung hierfür ist, das `$`-Zeichen zu „escapen“, indem es durch `$$` ersetzt wird, also `https://api.example.com/$$1`. Diese Ersetzung wird von Docker Compose unterstützt und hat nichts mit reproxy selbst zu tun. Eine andere Möglichkeit ist, `@` statt `$` zu verwenden, was auf reproxy-Ebene unterstützt wird, also `https://api.example.com/@1`_
## SSL-Unterstützung
Der SSL-Modus (standardmäßig keiner) kann auf `auto` (ACME/LE-Zertifikate), `static` (vorhandenes Zertifikat) oder `none` gesetzt werden. Wenn `auto` aktiviert ist, wird das SSL-Zertifikat automatisch für alle erkannten Servernamen ausgestellt. Der Benutzer kann dies überschreiben, indem er `--ssl.fqdn`-Wert(e) setzt. Im SSL-Modus `auto` und `static` fügt Reproxy automatisch die Header `X-Forwarded-Proto` und `X-Forwarded-Port` hinzu. Diese Header sind nützlich für Dienste hinter dem Proxy, um das ursprüngliche Protokoll (http oder https) und die vom Client verwendete Portnummer zu kennen.
Bei der Verwendung von ACME mit Discovery-Providern (docker, file, consul) werden SSL-Zertifikate automatisch für neu erkannte Server bezogen, ohne dass ein Neustart von reproxy erforderlich ist.
### ACME-Challenges
Reproxy unterstützt zwei Arten von ACME-Challenges zur Validierung von SSL-Zertifikaten:
1. **HTTP-01-Challenge** (Standard): Validiert den Domainbesitz, indem ein Token unter einer bestimmten HTTP-URL bereitgestellt wird. Erfordert, dass Port 80 öffentlich zugänglich ist.
2. **DNS-01-Challenge**: Validiert den Domainbesitz durch Erstellen von DNS-TXT-Einträgen. Diese Methode:
- erfordert keinen Zugriff auf Port 80
- funktioniert mit Wildcard-Zertifikaten
- erfordert eine unterstützte DNS-Provider-Konfiguration
#### Challenge-Auswahl
Reproxy bestimmt automatisch, welche Challenge-Methode verwendet wird, basierend auf Ihrer Konfiguration:
- **HTTP-01** (Standard): Wird verwendet, wenn kein DNS-Provider konfiguriert ist
- **DNS-01**: Wird verwendet, wenn ein DNS-Provider konfiguriert ist
Sie müssen keinen Challenge-Typ explizit auswählen – konfigurieren Sie einfach einen DNS-Provider, wenn Sie DNS-01-Challenges verwenden möchten.
DNS-Propagierungsprüfungen laufen standardmäßig nach 2 Minuten ab. Erhöhen Sie dies mit `--ssl.dns.propagation-timeout=5m` für Zonen, die Challenge-Einträge langsam veröffentlichen. Die Option `--ssl.dns.ttl` steuert die TTL des Eintrags und ändert nicht das Propagierungs-Timeout.
#### Derzeit unterstützte DNS-Provider
Reproxy enthält derzeit Unterstützung für die folgenden DNS-Provider:
- **Cloudflare**: `--ssl.dns.type=cloudflare --ssl.dns.cloudflare.api-token=TOKEN`
- **Route53 (AWS)**: `--ssl.dns.type=route53 --ssl.dns.route53.region=REGION --ssl.dns.route53.hosted-zone-id=ID`
- **Gandi**: `--ssl.dns.type=gandi --ssl.dns.gandi.bearer-token=TOKEN`
- **DigitalOcean**: `--ssl.dns.type=digitalocean --ssl.dns.digitalocean.api-token=TOKEN`
- **Hetzner**: `--ssl.dns.type=hetzner --ssl.dns.hetzner.api-token=TOKEN`
- **Linode**: `--ssl.dns.type=linode --ssl.dns.linode.api-token=TOKEN`
- **GoDaddy**: `--ssl.dns.type=godaddy --ssl.dns.godaddy.api-token=TOKEN`
- **Namecheap**: `--ssl.dns.type=namecheap --ssl.dns.namecheap.api-key=KEY --ssl.dns.namecheap.user=USER`
- **Scaleway**: `--ssl.dns.type=scaleway --ssl.dns.scaleway.secret-key=KEY --ssl.dns.scaleway.organization-id=ID`
- **Porkbun**: `--ssl.dns.type=porkbun --ssl.dns.porkbun.api-key=KEY --ssl.dns.porkbun.api-secret-key=SECRET`
- **DNSimple**: `--ssl.dns.type=dnsimple --ssl.dns.dnsimple.api-access-token=TOKEN --ssl.dns.dnsimple.account-id=ID`
- **DuckDNS**: `--ssl.dns.type=duckdns --ssl.dns.duckdns.api-token=TOKEN`
Beispiel mit Cloudflare als DNS-Provider:
```
export CLOUDFLARE_API_TOKEN=your_api_token
reproxy --ssl.type=auto [email protected] --ssl.fqdn=example.com
```
Die DNS-01-Challenge ist besonders nützlich, wenn:
- Dein Server Port 80 nicht öffentlich exponiert hat
- Du Wildcard-Zertifikate benötigst (z. B. *.example.com)
- Du dich hinter restriktiven Firewalls befindest
## Header
Reproxy ermöglicht es, eingehende Header zu bereinigen (zu entfernen), indem der Parameter `--drop-header` übergeben wird (kann wiederholt werden). Dieser Parameter kann nützlich sein, um sicherzustellen, dass einige der Header, die intern von den Diensten gesetzt werden, nicht vom Endbenutzer gesetzt/gefälscht werden können. Wenn beispielsweise einige der für die Authentifizierung zuständigen Dienste `X-Auth-User` und `X-Auth-Token` setzen, ist es wahrscheinlich sinnvoll, diese Header aus den eingehenden Anfragen zu entfernen, indem der Parameter `--drop-header=X-Auth-User --drop-header=X-Auth-Token` übergeben wird oder über die Umgebungsvariable `DROP_HEADERS=X-Auth-User,X-Auth-Token`.
Die entgegengesetzte Funktion, das Setzen ausgehender Header, wird ebenfalls unterstützt. Sie kann in vielen Fällen nützlich sein, beispielsweise zur Durchsetzung benutzerdefinierter CORS-Regeln, sicherheitsrelevanter Header und so weiter. Dies kann mit dem Parameter `--header` (kann wiederholt werden) oder der Umgebungsvariable `HEADER` erfolgen. So kann dies beispielsweise mit Docker Compose umgesetzt werden:
```yaml
environment:
- HEADER=
X-Frame-Options:SAMEORIGIN,
X-XSS-Protection:1; mode=block;,
Content-Security-Policy:default-src 'self'; style-src 'self' 'unsafe-inline';
```
## Protokollierung
Standardmäßig wird kein Anforderungsprotokoll erzeugt. Dies kann durch Setzen von `--logger.enabled` aktiviert werden. Das Protokoll (automatisch rotiert) hat das [Apache Combined Log Format](http://httpd.apache.org/docs/2.2/logs.html#combined)
Der Benutzer kann außerdem das stdout-Protokoll mit `--logger.stdout` aktivieren. Dies wirkt sich nicht auf die oben genannte Dateiprotokollierung aus, sondern gibt einige minimale Informationen über verarbeitete Anforderungen aus, etwa so:
```
2021/04/16 01:17:25.601 [INFO] GET - /echo/image.png - xxx.xxx.xxx.xxx - 200 (155400) - 371.661251ms
2021/04/16 01:18:18.959 [INFO] GET - /api/v1/params - xxx.xxx.xxx.xxx - 200 (74) - 1.217669m
```
## Assets-Server
Benutzer können den Assets-Server aktivieren (standardmäßig deaktiviert), um statische Dateien bereitzustellen. Solange `--assets.location` gesetzt ist, behandelt er jede nicht weitergeleitete Anfrage unter `assets.root` als Anfrage für statische Dateien. Der Assets-Server kann ohne jegliche Proxy-Provider verwendet werden; in diesem Modus fungiert reproxy als einfacher Webserver für den statischen Inhalt. Der Assets-Server unterstützt außerdem den „SPA-Modus" mit `--assets.spa`, bei dem alle nicht gefundenen Anfragen an `index.html` weitergeleitet werden.
Zusätzlich zum gemeinsamen Assets-Server werden mehrere benutzerdefinierte Assets-Server unterstützt. Jeder Provider hat eine andere Art, eine solche statische Regel zu definieren, und einige Provider unterstützen dies möglicherweise überhaupt nicht. Beispielsweise ergeben mehrere Asset-Server Sinn beim statischen Provider (Kommandozeilen-Provider), beim Datei-Provider und sogar beim Docker-Provider, jedoch ergibt es sehr wenig Sinn beim Consul-Catalog-Provider.
1. Statischer Provider – wenn das Quellelement mit `assets:` oder `spa:` beginnt, wird es als Datei-Server behandelt. Beispielsweise wird `*,assets:/web,/var/www,` alle Anfragen an `/web/*` mit einem Datei-Server über dem Verzeichnis `/var/www` bedienen.
2. Datei-Provider – durch Setzen der optionalen Felder `assets: true` oder `spa: true`. Hinweis: Das Feld `route` muss ein Pfadpräfix sein (z. B. `/`, `/web/`), kein Regex-Muster.
3. Docker-Provider – `reproxy.assets=web-root:location`, d. h. `reproxy.assets=/web:/var/www`. Der Wechsel in den SPA-Modus erfolgt durch Setzen von `reproxy.spa` auf `yes` oder `true`.
### Caching
Der Assets-Server unterstützt die Cache-Steuerung mit dem Parameter `--assets.cache=<duration>`. Eine Dauer von `0s` (Standard) deaktiviert die Cache-Steuerung. Eine Dauer ist eine Folge von Dezimalzahlen, jeweils mit optionalem Bruchteil und Einheitssuffix, wie z. B. „300ms", „1.5h" oder „2h45m". Gültige Zeiteinheiten sind „ns", „us" (oder „µs"), „ms", „s", „m", „h" und „d".
Es gibt zwei Möglichkeiten, die Cache-Dauer festzulegen:
1. Ein einzelner Wert für alle statischen Assets. Das ist so einfach wie `--assets.cache=48h`.
2. Benutzerdefinierte Dauer für verschiedene MIME-Typen. Sie sollte zwei Teile enthalten – den Standardwert und die Paare aus mime:duration. In der Kommandozeile sieht dies wie mehrere `--assets.cache`-Optionen aus, d. h. `--assets.cache=48h --assets.cache=text/html:24h --assets.cache=image/png:2h`. Umgebungswerte sollten durch Kommas getrennt sein, d. h. `ASSETS_CACHE=48h,text/html:24h,image/png:2h`
Eine benutzerdefinierte 404-Seite (nicht gefunden) kann mit dem Parameter `--assets.not-found=<path>` festgelegt werden. Der Pfad sollte relativ zum Assets-Stammverzeichnis sein.
## Verwendung von reproxy als Basis-Image
Die Bereitstellung rein statischer Inhalte ist einer der beliebten Anwendungsfälle. Üblicherweise wird dies für den separaten Frontend-Container verwendet, der nur die UI bereitstellt. Mit dem Assets-Server ist ein solcher Container nahezu trivial zu erstellen. Dies ist ein Beispiel aus dem Container, der [reproxy.io](http://reproxy.io) bereitstellt
```docker
FROM node:22-alpine as build
WORKDIR /build
COPY site/ /build
COPY README.md /build/src/index.md
RUN yarn --frozen-lockfile
RUN yarn build
RUN ls -la /build/public
FROM ghcr.io/umputun/reproxy
COPY --from=build /build/public /srv/site
EXPOSE 8080
USER app
ENTRYPOINT ["/srv/reproxy", "--assets.location=/srv/site"]
```
Alles, was es tun muss, ist, statische Assets an einen Ort zu kopieren und diesen Ort als `"--assets.location` an den reproxy-Einstiegspunkt zu übergeben.
## SPA-freundlicher Modus
Einige SPA-Anwendungen verlassen sich darauf, dass der Proxy 404 bei statischen Assets auf besondere Weise behandelt, indem er auf "/index.html" umleitet. Dies ähnelt der `try_files $uri $uri/ …`-Direktive von nginx und ist offenbar für moderne Web-Apps einigermaßen wichtig.
Dieser Modus ist standardmäßig deaktiviert und kann durch Setzen von `--assets.spa` oder der Umgebungsvariable `ASSETS_SPA=true` aktiviert werden.
## Weiterleitungen
Standardmäßig behandelt reproxy das Ziel als Proxy-Standort, d. h. es führt intern einen HTTP-Aufruf aus und gibt die Antwort an den Client zurück. Durch Voranstellen von `@code` vor die Ziel-URL kann dieses Verhalten jedoch in eine permanente (Statuscode 301) oder temporäre (Statuscode 302) Weiterleitung geändert werden. D. h. ein auf `@301 https://example.com/something` gesetztes Ziel bewirkt eine permanente HTTP-Weiterleitung zu `Location: https://example.com/something`
unterstützte Codes:
- `@301`, `@perm` – permanente Weiterleitung
- `@302`, `@temp`, `@tmp` – temporäre Weiterleitung
## Weitere Optionen
- `--gzip` aktiviert die gzip- (oder deflate-)Komprimierung für Antworten. Die Entscheidung wird pro Antwort anhand ihrer endgültigen Header getroffen:
- Medientypen, die `--gzip-exclude` entsprechen, werden unverändert gesendet. Der Wert ist eine kommagetrennte Liste exakter Typen (`image/png`) oder Präfixe (`audio/*`). Der Standard überspringt Audio, Video, komprimierte Bilder (jpeg, png, gif, webp, avif), woff-Schriftarten und gängige Archive. Eine benutzerdefinierte Liste ersetzt den Standard, und ein leerer Wert (`--gzip-exclude=`) schaltet die Ausschlüsse ab.
- Teilantworten (`206` oder jede Antwort mit `Content-Range`) werden niemals komprimiert, sodass `Range`-Anfragen weiterhin funktionieren.
- reproxy komprimiert keine Antworten erneut, die bereits `Content-Encoding` tragen. Das `Accept-Encoding` des Clients wird an das Upstream weitergeleitet, sodass ein Upstream, das selbst komprimiert, für seine Antworten entscheidet, und die Ausschlussliste gilt nur für die von reproxy durchgeführte Komprimierung.
- Eine komprimierte Antwort entfernt `Accept-Ranges` und die ursprüngliche `Content-Length`, und ein starker `ETag` wird schwach (`W/"..."`), da sich seine Bytes vom Original unterscheiden.
- `--max=N` erlaubt das Festlegen der maximalen Anfragegröße (Standard 64k). Ein Wert von `0` deaktiviert die Größenprüfung.
- `--timeout.*` verschiedene Timeouts sowohl für den Server als auch für den Proxy-Transport. Siehe den Abschnitt `timeout` in [Alle Anwendungsoptionen](#all-application-options). Ein Wert von null oder ein negativer Wert bedeutet, dass es keinen Timeout gibt.
- `--insecure` deaktiviert die SSL-Verifikation beim Zielhost. Dies ist nützlich für selbstsignierte Zertifikate.
## Standardports
Um die Notwendigkeit zu beseitigen, benutzerdefinierte Parameter/Umgebungsvariablen übergeben zu müssen, ist der Standardwert von `--listen` dynamisch und versucht, für die typischen Fälle sinnvoll und hilfreich zu sein:
- Wenn von Benutzern irgendetwas für `--listen` gesetzt wurde, wird die gesamte folgende Logik ignoriert und der übergebene host:port direkt verwendet.
- Wenn von Benutzern nichts für `--listen` gesetzt wurde und reproxy außerhalb des Docker-Containers läuft, ist der Standard `127.0.0.1:80` für den HTTP-Modus (`ssl.type=none`) und `127.0.0.1:443` für den SSL-Modus (`ssl.type=auto` oder `ssl.type=static`).
- Wenn von Benutzern nichts für `--listen` gesetzt wurde und reproxy innerhalb von Docker läuft, ist der Standard `0.0.0.0:8080` für den HTTP-Modus und `0.0.0.0:8443` für den SSL-Modus.
Ein weiterer Standard, der auf ähnliche dynamische Weise festgelegt wird, ist `--ssl.http-port`. Für den Lauf innerhalb des Docker-Containers wird er auf `8080` gesetzt und außerhalb auf `80`.
## Ping, Health Checks und Fail-over
reproxy stellt zu diesem Zweck zwei Endpunkte bereit:
- `/ping` antwortet mit `pong` und zeigt an, dass reproxy läuft und betriebsbereit ist
- `/health` gibt den Status `200 OK` zurück, wenn alle Zielserver auf ihre Ping-Anfrage mit `200` geantwortet haben, oder `417 Expectation Failed`, wenn einer der Server mit einem anderen Code als 200 geantwortet hat. Es gibt außerdem einen JSON-Body mit Details zu bestandenen/fehlgeschlagenen Diensten zurück.
Neben den oben genannten Endpunkten unterstützt reproxy optionale Live-Health-Checks. In diesem Fall (sofern aktiviert) wird jedes Ziel periodisch auf eine Ping-Antwort geprüft und fehlgeschlagene Zielrouten werden ausgeschlossen. Es ist möglich, dass mehrere identische Ziele vom selben oder von verschiedenen Anbietern zurückgegeben werden, und nur das bestandene wird ausgewählt. Wenn mehrere Übereinstimmungen gefunden und bestanden wurden, wird das letzte gemäß der `lb-type`-Strategie ausgewählt (standardmäßig zufällige Auswahl).
Um den Live-Health-Check zu aktivieren, sollte der Benutzer `--health-check.enabled` setzen (oder die Umgebungsvariable `HEALTH_CHECK_ENABLED=true`). Zur Anpassung des Prüfintervalls kann `--health-check.interval=` verwendet werden.
## Management-API
Optional, kann mit `--mgmt.enabled` aktiviert werden. Stellt 2 Endpunkte auf `mgmt.listen` (Adresse:Port) bereit:
- `GET /routes` – Liste aller entdeckten Routen
- `GET /metrics` – gibt Prometheus-Metriken zurück (`http_requests_total`, `response_status` und `http_response_time_seconds`)
Standardmäßig verwendet `http_response_time_seconds` rohe Anfragepfade als Labels, was bei dynamischen URLs (z. B. `/api/users/123`, `/api/users/456`) zu hoher Kardinalität führen kann. Verwenden Sie `--mgmt.low-cardinality`, um stattdessen auf Routenmuster (z. B. `^/api/users/(.*)`) umzuschalten, wodurch die Kardinalität der Metriken erheblich reduziert wird.
_siehe auch [examples/metrics](https://github.com/umputun/reproxy/tree/master/examples/metrics)_
## Fehlerberichterstattung
Reproxy gibt einen 502-Fehler (Bad Gateway) zurück, falls eine Anfrage zu keiner der bereitgestellten Routen und Assets passt. Falls ein unerwarteter interner Fehler auftritt, wird 500 zurückgegeben. Standardmäßig rendert reproxy die einfachste Textversion des Fehlers – „Server error". Das Setzen von `--error.enabled` aktiviert die standardmäßige HTML-Fehlermeldung, und mit `--error.template` kann der Benutzer eine beliebige benutzerdefinierte HTML-Template-Datei für das Fehler-Rendering festlegen. Das Template hat zwei Variablen: `{{.ErrCode}}` und `{{.ErrMessage}}`. Beispielsweise wird dieses Template `oh my! {{.ErrCode}} - {{.ErrMessage}}` zu `oh my! 502 - Bad Gateway` gerendert.
## Drosselung
---
[Read more](https://github.com/umputun/reproxy)