feat(selfhost-web): make webapp-server timeouts configurable (#6147)
Signed-off-by: Rodrigo Kellermann <kellermann@gmail.com> Co-authored-by: James George <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
parent
9861ee84ad
commit
40ac84c115
3 changed files with 48 additions and 14 deletions
|
|
@ -16,15 +16,18 @@ docker build -t hoppscotch-webapp-server .
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
|----------------------------------|------------------------------------|------------------------------------------------|
|
|----------------------------------|------------------------------------------------------------|------------------------------------------------|
|
||||||
| `WEBAPP_SERVER_PORT` | Server port | `3200` |
|
| `WEBAPP_SERVER_PORT` | Server port | `3200` |
|
||||||
| `FRONTEND_PATH` | Path to frontend assets | `/site/selfhost-web` (prod) or `../dist` (dev) |
|
| `WEBAPP_SERVER_READ_TIMEOUT` | HTTP read timeout (Go duration, e.g. `30s`; `0` disables) | `15s` |
|
||||||
| `WEBAPP_SERVER_SIGNING_SECRET` | Secret string for key derivation | None |
|
| `WEBAPP_SERVER_WRITE_TIMEOUT` | HTTP write timeout (Go duration, e.g. `30s`; `0` disables) | `15s` |
|
||||||
| `WEBAPP_SERVER_SIGNING_SEED` | Base64 encoded 32-byte seed | None |
|
| `WEBAPP_SERVER_IDLE_TIMEOUT` | HTTP idle timeout (Go duration, e.g. `2m`; `0` disables) | `60s` |
|
||||||
| `WEBAPP_SERVER_SIGNING_KEY` | Base64 encoded 64-byte private key | None |
|
| `FRONTEND_PATH` | Path to frontend assets | `/site/selfhost-web` (prod) or `../dist` (dev) |
|
||||||
| `WEBAPP_SERVER_SIGNING_KEY_FILE` | Custom path for key file | `/data/webapp-server/signing.key` |
|
| `WEBAPP_SERVER_SIGNING_SECRET` | Secret string for key derivation | None |
|
||||||
| `GO_ENV` | Set to `development` for dev mode | 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
|
## Signing Key Persistence
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,43 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultPort = 3200
|
DefaultPort = 3200
|
||||||
DefaultFrontendPath = "/site/selfhost-web"
|
DefaultFrontendPath = "/site/selfhost-web"
|
||||||
DevFrontendPath = "../dist"
|
DevFrontendPath = "../dist"
|
||||||
|
|
||||||
|
DefaultReadTimeout = 15 * time.Second
|
||||||
|
DefaultWriteTimeout = 15 * time.Second
|
||||||
|
DefaultIdleTimeout = 60 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Port int
|
Port int
|
||||||
FrontendPath string
|
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
|
// 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")
|
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
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,14 +62,15 @@ func main() {
|
||||||
|
|
||||||
addr := fmt.Sprintf(":%d", cfg.Port)
|
addr := fmt.Sprintf(":%d", cfg.Port)
|
||||||
|
|
||||||
// NOTE: these timeouts are pretty conservative
|
// NOTE: timeouts default to conservative values but can be overridden
|
||||||
// bump them if you're serving huge bundles over slow connections
|
// 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{
|
httpServer := &http.Server{
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
Handler: mux,
|
Handler: mux,
|
||||||
ReadTimeout: 15 * time.Second,
|
ReadTimeout: cfg.ReadTimeout,
|
||||||
WriteTimeout: 15 * time.Second,
|
WriteTimeout: cfg.WriteTimeout,
|
||||||
IdleTimeout: 60 * time.Second,
|
IdleTimeout: cfg.IdleTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue