Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 17 additions & 1 deletion gateway/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"net/textproto"
"net/url"
"os"
gopath "path"
"regexp"
"runtime/debug"
Expand Down Expand Up @@ -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/<path>)
// (it serves requests like GET /ipfs/QmVRzPKPzNtSrEzBFm2UZfxmPAgnaLke4DMcerbsGGSaFe/link)
type handler struct {
Expand Down Expand Up @@ -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 {
Expand Down
Loading