Packages: two minutes per body read for uploads, not 15 seconds

872fcb1 · Gabriel Morell · 2026-10-27 20:04

6 files +15 -2
Message
{commit_body(@commit)}

Files changed

modified lib/git_gud_web/controllers/package_registry_controller.ex
+4 −1
@@ -208,7 +208,10 @@ defmodule GitGudWeb.PackageRegistryController do
208 208 {:ok, conn.body_params, conn}
209 209
210 210 true ->
211 − case Plug.Conn.read_body(conn, length: 8_000_000) do
211 + case Plug.Conn.read_body(conn,
212 + length: 8_000_000,
213 + read_timeout: GitGudWeb.Plugs.PackageUploadParser.read_timeout()
214 + ) do
212 215 {:ok, chunk, conn} ->
213 216 {:ok, IO.iodata_to_binary(Enum.reverse([chunk | acc])), conn}
214 217
modified lib/git_gud_web/plugs/package_upload_parser.ex
+11 −1
@@ -30,12 +30,22 @@ defmodule GitGudWeb.Plugs.PackageUploadParser do
30 30 # Anything genuinely larger belongs in LFS or the OCI registry.
31 31 @max_upload_bytes 200_000_000
32 32
33 + # Each socket read (1 MB) may take this long. Plug's default, 15s, is a
34 + # 66 KB/s floor: since Bandit 1.14 stopped letting HTTP/2 control frames
35 + # extend a body read, a CI runner pushing a 16 MB APK over a slow link
36 + # got a 408 "Body read timeout" midway. Two minutes is an 8 KB/s floor.
37 + @read_timeout 120_000
38 +
33 39 @parser_opts Plug.Parsers.init(
34 40 parsers: [:multipart],
35 41 pass: ["*/*"],
36 − length: @max_upload_bytes
42 + length: @max_upload_bytes,
43 + read_timeout: @read_timeout
37 44 )
38 45
46 + @doc "The per-read timeout for package upload bodies, for controllers reading them raw."
47 + def read_timeout, do: @read_timeout
48 +
39 49 @impl true
40 50 def init(opts), do: opts
41 51

Parents: 727d1f1