From 20c773c9c4bb0d8df0520da6b3e68968ca9099f3 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Mon, 21 Sep 2026 00:03:32 +0200 Subject: [PATCH] 502 zuordnen: Proxy Manager selbst oder ein HTTP-Proxy davor Ein 502 hat zwei moegliche Absender, und sie sehen gleich aus: - Der Proxy Manager selbst. Sein nginx steht, der Dienst dahinter nicht. Nachgemessen: nach einem Neustart antwortet die Schnittstelle erst nach rund zehn Sekunden mit 200 - davor kommen 000, dann 502. - Ein HTTP-Proxy davor, der localhost:81 von SEINEM Rechner aus zu erreichen versucht und scheitert. Unterscheiden laesst sich das an der Server-Kopfzeile: der Proxy Manager nennt sich "openresty", ein Proxy traegt sich zusaetzlich mit "Via:" ein. Beide Faelle nachgestellt und die Kopfzeilen abgenommen. Die Meldung wertet das jetzt aus und sagt im ersten Fall "kurz warten, er startet noch", im zweiten "das war nicht der Proxy Manager, pruefe noproxy". Vorher stand dort pauschal "Serverfehler" mit einem Verweis auf noproxy - der im haeufigeren Fall in die falsche Richtung zeigte. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 20 ++++++++++++++++++ README_en.md | 19 +++++++++++++++++ scripts/cmk-manage.sh | 49 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 62e3529..2dc6668 100644 --- a/README.md +++ b/README.md @@ -1222,8 +1222,28 @@ Die andere Richtung sieht so aus: |---|---|---| | `400`/`401` | Der Proxy Manager lehnt ab | Konto/Kennwort in der `.env`, oder das Konto gibt es nicht → `npm-reset` | | `000` | gar keine Antwort | Container aus? Port frei? – der Befehl prüft beides und sagt, welches zutrifft | +| `502` | zwei mögliche Absender – siehe unten | die Zeile `Antwortete:` verrät welchen | | `5xx` + HTML | etwas anderes antwortet | meist der HTTP-Proxy; die erste Zeile der HTML-Antwort wird mit angezeigt | +**Ein `502` hat zwei Absender**, und sie fühlen sich gleich an. Unterscheiden +lassen sie sich an der `Server`-Kopfzeile, die die Meldung mit ausgibt: + +| `Antwortete:` | wer es war | was zu tun ist | +|---|---|---| +| `openresty` (ohne `Via:`) | **der Proxy Manager selbst** – nginx steht, der Dienst dahinter nicht | meist startet er noch: nach einem Neustart dauert es rund **zehn Sekunden**, bis die Schnittstelle antwortet. Sonst `logs` bzw. `proxy restart` | +| `squid`, `Via: …` o. ä. | **ein HTTP-Proxy davor** | `noproxy` – die Anfrage ging gar nicht bis zum Proxy Manager | + +Der zweite Fall ist tückisch, weil der Proxy den 502 erzeugt, während er +`localhost:81` **von seinem eigenen Rechner aus** zu erreichen versucht. Mit +einem einzigen Aufruf auseinanderzuhalten: + +```bash +curl -si --noproxy '*' http://localhost:81/api/tokens -X POST \ + -H 'Content-Type: application/json' -d '{}' | head -3 +``` + +Kommt damit etwas anderes heraus als ohne `--noproxy`, war der Proxy dazwischen. + Antwortet HTML statt JSON, steht es ausdrücklich da – samt erster Zeile, an der man erkennt, wer da geantwortet hat: diff --git a/README_en.md b/README_en.md index e6271d4..641fe56 100644 --- a/README_en.md +++ b/README_en.md @@ -1220,8 +1220,27 @@ The other direction looks like this: |---|---|---| | `400`/`401` | the Proxy Manager refuses | account/password in `.env`, or the account does not exist → `npm-reset` | | `000` | no answer at all | container down? port free? – the command checks both and says which applies | +| `502` | two possible senders – see below | the `Antwortete:` line reveals which | | `5xx` + HTML | something else answered | usually the HTTP proxy; the first line of the HTML reply is shown | +**A `502` has two senders**, and they feel identical. The `Server` header, +which the message prints, tells them apart: + +| `Antwortete:` | who it was | what to do | +|---|---|---| +| `openresty` (no `Via:`) | **the Proxy Manager itself** – nginx is up, the service behind it is not | usually it is still starting: after a restart it takes about **ten seconds** for the API to answer. Otherwise `logs` or `proxy restart` | +| `squid`, `Via: …` etc. | **an HTTP proxy in front** | `noproxy` – the request never reached the Proxy Manager | + +The second case is treacherous, because the proxy produces the 502 while trying +to reach `localhost:81` **from its own machine**. One call tells them apart: + +```bash +curl -si --noproxy '*' http://localhost:81/api/tokens -X POST \ + -H 'Content-Type: application/json' -d '{}' | head -3 +``` + +If that differs from the result without `--noproxy`, the proxy was in between. + If HTML arrives instead of JSON, it says so explicitly – including the first line, which reveals who answered: diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index 717dd4d..182d007 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -3772,9 +3772,9 @@ EOF # Antwort, HTTP-Code und curls eigene Fehlermeldung getrennt # einsammeln - ohne die drei laesst sich hinterher nicht sagen, WORAN # es lag, und genau das ist hier der haeufigste Zeitfresser. - local body code cerr rc=0 - cerr="$(mktemp)" - body="$(curl -sS --max-time 20 --noproxy '*' -w '\n%{http_code}' \ + local body code cerr hdrf rc=0 + cerr="$(mktemp)"; hdrf="$(mktemp)" + body="$(curl -sS --max-time 20 --noproxy '*' -w '\n%{http_code}' -D "$hdrf" \ -X POST "$base/api/tokens" \ -H 'Content-Type: application/json' \ -d "{\"identity\":\"$NPM_ADMIN_EMAIL\",\"secret\":\"$NPM_ADMIN_PASSWORD\"}" \ @@ -3784,7 +3784,7 @@ EOF local tok; tok="$(json_str "$body" token)" if [ -n "$tok" ]; then - rm -f "$cerr" + rm -f "$cerr" "$hdrf" printf '%s' "$tok" return 0 fi @@ -3796,6 +3796,15 @@ EOF local cmsg; cmsg="$(sed -n '1p' "$cerr" 2>/dev/null)" if [ -n "$cmsg" ]; then printf ' curl sagt : %s\n' "$cmsg" >&2; fi rm -f "$cerr" + # Wer hat geantwortet? Der Proxy Manager nennt sich "openresty", ein + # HTTP-Proxy traegt sich ueblicherweise mit "Via:" ein. Daran laesst + # sich ein 502 eindeutig zuordnen - sonst raet man zwischen + # "Dienst startet noch" und "Proxy dazwischen". + local srv via + srv="$(sed -n 's/^[Ss]erver:[[:space:]]*//p' "$hdrf" 2>/dev/null | tr -d '\r' | head -1)" + via="$(sed -n 's/^[Vv]ia:[[:space:]]*//p' "$hdrf" 2>/dev/null | tr -d '\r' | head -1)" + rm -f "$hdrf" + if [ -n "$srv" ]; then printf ' Antwortete : %s%s\n' "$srv" "${via:+ (ueber $via)}" >&2; fi # Der Proxy Manager verpackt seine Meldung in "error" - sie ist die # nuetzlichste Zeile ueberhaupt und gehoert nach oben, nicht ans Ende. local m; m="$(json_str "$body" message)" @@ -3858,11 +3867,35 @@ EOF printf ' -> curl nennt einen Proxy. Pruefen: %s noproxy\n' "$SELF" >&2 ;; esac ;; - 5??) - printf ' Es hat etwas geantwortet, aber mit einem Serverfehler. - Kommt die Antwort ueberhaupt vom Proxy Manager? Ein + 502|503|504) + case "$srv" in + openresty*|nginx*) + if [ -z "$via" ]; then + printf ' Der Proxy Manager selbst hat geantwortet (%s) - aber der + Dienst DAHINTER ist nicht erreichbar. Das ist normal, solange er + noch startet: nach einem Neustart dauert es rund zehn Sekunden, + bis die Schnittstelle antwortet. + + Kurz warten und noch einmal, sonst ins Protokoll sehen: + %s logs + %s proxy restart\n' "$srv" "$SELF" "$SELF" >&2 + else + printf ' Die Antwort kam ueber einen Proxy (Via: %s), nicht direkt. + Pruefen: %s noproxy\n' "$via" "$SELF" >&2 + fi ;; + '') + printf ' Es hat etwas geantwortet, nennt sich aber nicht. Ein HTTP-Proxy im Netz antwortet an dieser Stelle gern selbst: - %s noproxy\n' "$SELF" >&2 + %s noproxy\n' "$SELF" >&2 ;; + *) + printf ' Geantwortet hat "%s" - das ist nicht der Proxy Manager + (der nennt sich "openresty"). Vermutlich ein HTTP-Proxy oder ein + anderer Dienst auf dem Port: + %s noproxy\n' "$srv" "$SELF" >&2 ;; + esac + ;; + 5??) + printf ' Es hat etwas geantwortet, aber mit einem Serverfehler.\n' >&2 ;; *) printf ' Unerwartete Antwort - erwartet wurde ein Feld "token".\n' >&2