From d21f4222a47843cdfcbd10fa4fa26b106b61290b Mon Sep 17 00:00:00 2001 From: Robbie Court Date: Sun, 12 Jul 2026 12:15:32 +0100 Subject: [PATCH] Apply timeout flags after merge so explicit zero disables the timeout mergo.Merge with WithOverride does not override a destination field with a zero-value source field. An explicit `-read_timeout 0` parses to the zero value, which is indistinguishable from an unset flag, so it never overrode the non-zero default ReadTimeout (15s). The documented behaviour "zero or negative value means no timeout" was therefore only reachable with a negative duration. Re-apply the read/write timeout flags directly after the flag merge when the user actually provided them, using flag.Visit, so an explicit 0 disables the timeout as documented while an unset flag keeps the default. --- app.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app.go b/app.go index 3d1d9a0..b581263 100644 --- a/app.go +++ b/app.go @@ -284,6 +284,21 @@ func (a *app) ParseConfig(args []string) (*simpleuploadserver.ServerConfig, erro } log.Printf("merged flag config: %+v", config) + // mergo.WithOverride does not override a destination field with a zero-value + // source field. An explicit `-read_timeout 0` parses to the zero value, which + // is indistinguishable from an unset flag, so it never overrides the non-zero + // default ReadTimeout and the documented "zero ... means no timeout" cannot be + // selected. Apply the timeout flags directly when the user actually provided + // them so that an explicit 0 disables the timeout as documented. + a.flagSet.Visit(func(f *flag.Flag) { + switch f.Name { + case "read_timeout": + config.ReadTimeout = Duration(a.readTimeout) + case "write_timeout": + config.WriteTimeout = Duration(a.writeTimeout) + } + }) + v := config.AsConfig() return &v, nil }