tweaks

5195c69 · gmorell · 2026-05-22 19:36

2 files +26 -5

Files changed

modified lib/git_gud_web/controllers/runner_controller.ex
+20 −5
@@ -527,11 +527,9 @@ defmodule GitGudWeb.RunnerController do
527 527
528 528 # Loud failure trumps a silent framing bug. Empty protobuf
529 529 # bodies look valid by spec but break Connect-Go's unary
530 # decoder AND, downstream, the HTTP/1.1 keepalive stream
531 # (next request reads mid-stream — see Bandit.HTTPError
532 # `Request line HTTP error`). Each RPC handler is expected
533 # to populate at least one non-default field; this catches
534 # any new endpoint that forgets.
530 + # decoder. Each RPC handler is expected to populate at
531 + # least one non-default field; this catches any new
532 + # endpoint that forgets.
535 533 if byte_size(body) == 0 do
536 534 require Logger
537 535
@@ -543,6 +541,7 @@ defmodule GitGudWeb.RunnerController do
543 541
544 542 conn
545 543 |> put_resp_content_type(echoed_ct, nil)
544 + |> close_runner_conn()
546 545 |> send_resp(200, body)
547 546
548 547 {:json, _} ->
@@ -550,10 +549,26 @@ defmodule GitGudWeb.RunnerController do
550 549
551 550 conn
552 551 |> put_resp_content_type("application/json", nil)
552 + |> close_runner_conn()
553 553 |> send_resp(200, body)
554 554 end
555 555 end
556 556
557 + # Disable HTTP/1.1 keep-alive for runner-protocol responses.
558 + #
559 + # Bandit + forgejo-runner's Connect-Go HTTP/1.1 client get into
560 + # framing trouble when our content-length disagrees with bytes-
561 + # on-wire by even one byte: the next request on the same socket
562 + # parses from inside the previous response body, the request line
563 + # looks like garbage, Phoenix returns 404, and the runner reports
564 + # the "unimplemented: 404 Not Found" error. The runner only sends
565 + # one request per logical operation anyway, so the keep-alive
566 + # savings are minimal; force `Connection: close` to make every
567 + # response its own TCP session and the failure class disappears.
568 + defp close_runner_conn(conn) do
569 + Plug.Conn.put_resp_header(conn, "connection", "close")
570 + end
571 +
557 572 # ── helpers ──────────────────────────────────────────────────────────
558 573
559 574 defp authenticate(conn) do
modified lib/git_gud_web/plugs/twirp.ex
+6 −0
@@ -36,6 +36,12 @@ defmodule GitGudWeb.Plugs.Twirp do
36 36
37 37 conn
38 38 |> put_resp_content_type("application/json", nil)
39 + # Match the runner-protocol success path: force `Connection:
40 + # close` so the runner opens a fresh TCP connection for its
41 + # next request. Eliminates the HTTP/1.1 keep-alive framing-
42 + # cascade where one mis-sized response corrupts the parse of
43 + # the next request line.
44 + |> put_resp_header("connection", "close")
39 45 |> send_resp(status, body)
40 46 end
41 47

Parents: 296556b