carlos / platform Public

scripts: region gate takes the status from curl and the version from the final response only (review fix)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 5f20390224f59ec25c452090f592101c31fddf80 parent 779af1c
2 files changed, +50 −4
  • region_service_gate_test.go +42 −0
  • scripts/region-service-gate.sh +8 −4
diff --git a/region_service_gate_test.go b/region_service_gate_test.go
index d31d970e1..1a33241b8 100644
--- a/region_service_gate_test.go
+++ b/region_service_gate_test.go
@@ -48,3 +48,45 @@ func TestRegionServiceGate(t *testing.T) {
t.Fatalf("the gate went through a proxy: %v %s", err, out)
}
}
+
+// Review fix round 1: the gate judges the final response only. The status is
+// the final status line, not any header that starts with "HTTP", and
+// X-Carlos-Version is read from the final response's header block, not from
+// an informational response ahead of it.
+func TestRegionServiceGateJudgesTheFinalResponse(t *testing.T) {
+ const version = "abc1234"
+ gate := func(h http.HandlerFunc) (string, error) {
+ srv := httptest.NewTLSServer(h)
+ defer srv.Close()
+ host, port, _ := net.SplitHostPort(srv.Listener.Addr().String())
+ cmd := exec.Command("./scripts/region-service-gate.sh", "probe.example", version, host)
+ cmd.Env = append(cmd.Environ(), "GATE_PORT="+port, "GATE_INSECURE=1", "GATE_SKIP_PUBLIC=1")
+ out, err := cmd.CombinedOutput()
+ return string(out), err
+ }
+ // A 500 that carries a header looking like a status line and the right version.
+ if out, err := gate(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("X-Carlos-Version", version)
+ w.Header().Set("HTTP-Debug", "200")
+ w.WriteHeader(http.StatusInternalServerError)
+ }); err == nil || !strings.Contains(out, "FAIL") {
+ t.Errorf("a 500 with an HTTP-Debug header passed: %s", out)
+ }
+ // 103 Early Hints carries the version; the final 200 does not.
+ if out, err := gate(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("X-Carlos-Version", version)
+ w.WriteHeader(http.StatusEarlyHints)
+ w.Header().Del("X-Carlos-Version")
+ w.WriteHeader(http.StatusOK)
+ }); err == nil || !strings.Contains(out, "FAIL") {
+ t.Errorf("a version only on the 103 passed: %s", out)
+ }
+ // Both blocks carry the version: the final one is right, so it passes.
+ if out, err := gate(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("X-Carlos-Version", version)
+ w.WriteHeader(http.StatusEarlyHints)
+ w.WriteHeader(http.StatusOK)
+ }); err != nil {
+ t.Errorf("a 103 and a 200 that both carry the version failed: %v %s", err, out)
+ }
+}
diff --git a/scripts/region-service-gate.sh b/scripts/region-service-gate.sh
index ea6311f4a..a339f723f 100755
--- a/scripts/region-service-gate.sh
+++ b/scripts/region-service-gate.sh
@@ -22,16 +22,20 @@ trap 'rm -f "$hdr"' EXIT
fail=0
check() { # <label> <expected-ip or ""> [curl args...]
local label="$1" eip="$2"; shift 2
- local ip status version
+ local out ip status version
# -q must be first: it stops curl reading ~/.curlrc. $insecure is
# unquoted on purpose so that empty expands to nothing (bash 3.2 safe).
- ip="$(curl -q -s $insecure --noproxy '*' -D "$hdr" -o /dev/null -w '%{remote_ip}' --max-time 20 "$@" "https://$host:$port/")" || {
+ # The status is curl's own final %{http_code}, never a header that happens
+ # to start with "HTTP". The version is read only from the final response's
+ # header block: -D also dumps 1xx blocks (103 Early Hints), so the block
+ # starts again at every real status line ("HTTP/x.y NNN").
+ out="$(curl -q -s $insecure --noproxy '*' -D "$hdr" -o /dev/null -w '%{remote_ip} %{http_code}' --max-time 20 "$@" "https://$host:$port/")" || {
echo "FAIL $label: request failed"; fail=1; return; }
+ read -r ip status <<<"$out"
if [ -n "$eip" ] && [ "$ip" != "$eip" ]; then
echo "FAIL $label: connected to $ip, not $eip"; fail=1; return
fi
- status="$(awk 'toupper($1) ~ /^HTTP/ {s=$2} END {print s}' "$hdr")"
- version="$(awk -F': *' 'tolower($1)=="x-carlos-version" {gsub(/\r/,"",$2); print $2}' "$hdr")"
+ version="$(awk -F': *' '/^HTTP\/[0-9.]+ [0-9][0-9][0-9]/ {v=""; next} tolower($1)=="x-carlos-version" {gsub(/\r/,"",$2); v = (v=="" ? $2 : v "," $2)} END {print v}' "$hdr")"
if [[ "$status" != 2* ]]; then echo "FAIL $label: status $status"; fail=1; return; fi
if [ "$version" != "$want" ]; then echo "FAIL $label: X-Carlos-Version '$version', want '$want'"; fail=1; return; fi
echo "ok $label: $status $version"