diff --git a/packages/hoppscotch-selfhost-web/webapp-server/README.md b/packages/hoppscotch-selfhost-web/webapp-server/README.md index 06a2c614..224d00c6 100644 --- a/packages/hoppscotch-selfhost-web/webapp-server/README.md +++ b/packages/hoppscotch-selfhost-web/webapp-server/README.md @@ -16,15 +16,18 @@ docker build -t hoppscotch-webapp-server . ## Configuration -| Variable | Description | Default | -|----------------------------------|------------------------------------|------------------------------------------------| -| `WEBAPP_SERVER_PORT` | Server port | `3200` | -| `FRONTEND_PATH` | Path to frontend assets | `/site/selfhost-web` (prod) or `../dist` (dev) | -| `WEBAPP_SERVER_SIGNING_SECRET` | Secret string for key derivation | None | -| `WEBAPP_SERVER_SIGNING_SEED` | Base64 encoded 32-byte seed | None | -| `WEBAPP_SERVER_SIGNING_KEY` | Base64 encoded 64-byte private key | None | -| `WEBAPP_SERVER_SIGNING_KEY_FILE` | Custom path for key file | `/data/webapp-server/signing.key` | -| `GO_ENV` | Set to `development` for dev mode | None | +| Variable | Description | Default | +|----------------------------------|------------------------------------------------------------|------------------------------------------------| +| `WEBAPP_SERVER_PORT` | Server port | `3200` | +| `WEBAPP_SERVER_READ_TIMEOUT` | HTTP read timeout (Go duration, e.g. `30s`; `0` disables) | `15s` | +| `WEBAPP_SERVER_WRITE_TIMEOUT` | HTTP write timeout (Go duration, e.g. `30s`; `0` disables) | `15s` | +| `WEBAPP_SERVER_IDLE_TIMEOUT` | HTTP idle timeout (Go duration, e.g. `2m`; `0` disables) | `60s` | +| `FRONTEND_PATH` | Path to frontend assets | `/site/selfhost-web` (prod) or `../dist` (dev) | +| `WEBAPP_SERVER_SIGNING_SECRET` | Secret string for key derivation | None | +| `WEBAPP_SERVER_SIGNING_SEED` | Base64 encoded 32-byte seed | None | +| `WEBAPP_SERVER_SIGNING_KEY` | Base64 encoded 64-byte private key | None | +| `WEBAPP_SERVER_SIGNING_KEY_FILE` | Custom path for key file | `/data/webapp-server/signing.key` | +| `GO_ENV` | Set to `development` for dev mode | None | ## Signing Key Persistence diff --git a/packages/hoppscotch-selfhost-web/webapp-server/internal/config/config.go b/packages/hoppscotch-selfhost-web/webapp-server/internal/config/config.go index 8d4dafa9..e5f48fad 100644 --- a/packages/hoppscotch-selfhost-web/webapp-server/internal/config/config.go +++ b/packages/hoppscotch-selfhost-web/webapp-server/internal/config/config.go @@ -4,17 +4,43 @@ import ( "log" "os" "strconv" + "time" ) const ( DefaultPort = 3200 DefaultFrontendPath = "/site/selfhost-web" DevFrontendPath = "../dist" + + DefaultReadTimeout = 15 * time.Second + DefaultWriteTimeout = 15 * time.Second + DefaultIdleTimeout = 60 * time.Second ) type Config struct { Port int FrontendPath string + ReadTimeout time.Duration + WriteTimeout time.Duration + IdleTimeout time.Duration +} + +// parseDuration reads a Go duration string from an env var (e.g. "30s", "2m", "0"). +// A value of "0" is valid and disables the timeout (net/http semantics). +// If the variable is unset or invalid, it logs a warning and returns the fallback. +func parseDuration(envKey string, fallback time.Duration) time.Duration { + if s := os.Getenv(envKey); s != "" { + if d, err := time.ParseDuration(s); err == nil && d >= 0 { + if d == 0 { + log.Printf("Using %s from environment: %s (timeout disabled)", envKey, s) + } else { + log.Printf("Using %s from environment: %s", envKey, s) + } + return d + } + log.Printf("Warning: Invalid %s value '%s', using default %v", envKey, s, fallback) + } + return fallback } // Load reads config from env vars with sensible defaults @@ -46,5 +72,9 @@ func Load() *Config { log.Println("Running in production mode, using frontend path: /site/selfhost-web") } + cfg.ReadTimeout = parseDuration("WEBAPP_SERVER_READ_TIMEOUT", DefaultReadTimeout) + cfg.WriteTimeout = parseDuration("WEBAPP_SERVER_WRITE_TIMEOUT", DefaultWriteTimeout) + cfg.IdleTimeout = parseDuration("WEBAPP_SERVER_IDLE_TIMEOUT", DefaultIdleTimeout) + return cfg } diff --git a/packages/hoppscotch-selfhost-web/webapp-server/main.go b/packages/hoppscotch-selfhost-web/webapp-server/main.go index 9a9d6a64..a1febec0 100644 --- a/packages/hoppscotch-selfhost-web/webapp-server/main.go +++ b/packages/hoppscotch-selfhost-web/webapp-server/main.go @@ -62,14 +62,15 @@ func main() { addr := fmt.Sprintf(":%d", cfg.Port) - // NOTE: these timeouts are pretty conservative - // bump them if you're serving huge bundles over slow connections + // NOTE: timeouts default to conservative values but can be overridden + // via WEBAPP_SERVER_READ_TIMEOUT, WEBAPP_SERVER_WRITE_TIMEOUT, WEBAPP_SERVER_IDLE_TIMEOUT + // (Go duration strings, e.g. "30s", "2m", "0" to disable) httpServer := &http.Server{ Addr: addr, Handler: mux, - ReadTimeout: 15 * time.Second, - WriteTimeout: 15 * time.Second, - IdleTimeout: 60 * time.Second, + ReadTimeout: cfg.ReadTimeout, + WriteTimeout: cfg.WriteTimeout, + IdleTimeout: cfg.IdleTimeout, } go func() {