diff --git a/CHANGELOG.md b/CHANGELOG.md index c76d622d4..a72605f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The following emojis are used to highlight certain changes: ### Added +- `gateway`: Added a configurable fallback timeout for the gateway handler, defaulting to 1 hour, overridable via the BOXO_GATEWAY_REQUEST_TIMEOUT environment variable. - `routing/http`: `GET /routing/v1/dht/closest/peers/{key}` per [IPIP-476](https://github.com/ipfs/specs/pull/476) ### Changed diff --git a/gateway/handler.go b/gateway/handler.go index bc8c5da71..97a4f59fe 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -9,6 +9,7 @@ import ( "net/http" "net/textproto" "net/url" + "os" gopath "path" "regexp" "runtime/debug" @@ -42,6 +43,21 @@ var ( noModtime = time.Unix(0, 0) // disables Last-Modified header if passed as modtime ) +// fallbackRequestTimeout defines the hard per-request timeout for the gateway handler. +// It defaults to 1h, but can be overridden via the BOXO_GATEWAY_REQUEST_TIMEOUT env var, +// which accepts Go duration strings (e.g., "90m", "2h", "5400s"). +var fallbackRequestTimeout = time.Hour + +func init() { + if v := os.Getenv("BOXO_GATEWAY_REQUEST_TIMEOUT"); v != "" { + if d, err := time.ParseDuration(v); err == nil && d > 0 { + fallbackRequestTimeout = d + } else { + log.Warnw("invalid BOXO_GATEWAY_REQUEST_TIMEOUT, using default 1h", "value", v, "error", err) + } + } +} + // handler is a HTTP handler that serves IPFS objects (accessible by default at /ipfs/) // (it serves requests like GET /ipfs/QmVRzPKPzNtSrEzBFm2UZfxmPAgnaLke4DMcerbsGGSaFe/link) type handler struct { @@ -159,7 +175,7 @@ func (i *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer panicHandler(w) // the hour is a hard fallback, we don't expect it to happen, but just in case - ctx, cancel := context.WithTimeout(r.Context(), time.Hour) + ctx, cancel := context.WithTimeout(r.Context(), fallbackRequestTimeout) defer cancel() if withCtxWrap, ok := i.backend.(WithContextHint); ok {