1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-12-23 22:11:10 +02:00
Files
imgproxy/server/config.go
2025-09-30 13:24:23 +02:00

147 lines
5.4 KiB
Go

package server
import (
"errors"
"fmt"
"time"
"github.com/imgproxy/imgproxy/v3/ensure"
"github.com/imgproxy/imgproxy/v3/env"
"github.com/imgproxy/imgproxy/v3/server/responsewriter"
)
var (
IMGPROXY_PORT = env.Describe("IMGPROXY_PORT", "port")
IMGPROXY_NETWORK = env.Describe("IMGPROXY_NETWORK", "tcp|tcp4|tcp6|udp|udp4|udp6|unix|unixgram|unixpacket")
IMGPROXY_BIND = env.Describe("IMGPROXY_BIND", "address:port, path to unix socket, etc")
IMGPROXY_PATH_PREFIX = env.Describe("IMGPROXY_PATH_PREFIX", "string")
IMGPROXY_MAX_CLIENTS = env.Describe("IMGPROXY_MAX_CLIENTS", "number, 0 means unlimited")
IMGPROXY_TIMEOUT = env.Describe("IMGPROXY_TIMEOUT", "seconds > 0")
IMGPROXY_READ_REQUEST_TIMEOUT = env.Describe("IMGPROXY_READ_REQUEST_TIMEOUT", "seconds > 0")
IMGPROXY_KEEP_ALIVE_TIMEOUT = env.Describe("IMGPROXY_KEEP_ALIVE_TIMEOUT", "seconds >= 0")
IMGPROXY_GRACEFUL_STOP_TIMEOUT = env.Describe("IMGPROXY_GRACEFUL_STOP_TIMEOUT", "seconds >= 0")
IMGPROXY_ALLOW_ORIGIN = env.Describe("IMGPROXY_ALLOW_ORIGIN", "string")
IMGPROXY_SECRET = env.Describe("IMGPROXY_SECRET", "string")
IMGPROXY_DEVELOPMENT_ERRORS_MODE = env.Describe("IMGPROXY_DEVELOPMENT_ERRORS_MODE", "boolean")
IMGPROXY_SO_REUSEPORT = env.Describe("IMGPROXY_SO_REUSEPORT", "boolean")
IMGPROXY_HEALTH_CHECK_PATH = env.Describe("IMGPROXY_HEALTH_CHECK_PATH", "string")
IMGPROXY_FREE_MEMORY_INTERVAL = env.Describe("IMGPROXY_FREE_MEMORY_INTERVAL", "seconds >= 0")
IMGPROXY_LOG_MEM_STATS = env.Describe("IMGPROXY_LOG_MEM_STATS", "boolean")
)
// Config represents HTTP server config
type Config struct {
Network string // Network type (tcp, unix)
Bind string // Bind address
PathPrefix string // Path prefix for the server
MaxClients int // Maximum number of concurrent clients
RequestTimeout time.Duration // Timeout for requests
ReadRequestTimeout time.Duration // Timeout for reading requests
KeepAliveTimeout time.Duration // Timeout for keep-alive connections
GracefulStopTimeout time.Duration // Timeout for graceful shutdown
CORSAllowOrigin string // CORS allowed origin
Secret string // Secret for authorization
DevelopmentErrorsMode bool // Enable development mode for detailed error messages
SocketReusePort bool // Enable SO_REUSEPORT socket option
HealthCheckPath string // Health check path from config
ResponseWriter responsewriter.Config // Response writer config
// TODO: We are not sure where to put it yet
FreeMemoryInterval time.Duration // Interval for freeing memory
LogMemStats bool // Log memory stats
}
// NewDefaultConfig returns default config values
func NewDefaultConfig() Config {
return Config{
Network: "tcp",
Bind: ":8080",
PathPrefix: "",
MaxClients: 2048,
RequestTimeout: 10 * time.Second,
ReadRequestTimeout: 10 * time.Second,
KeepAliveTimeout: 10 * time.Second,
GracefulStopTimeout: 20 * time.Second,
CORSAllowOrigin: "",
Secret: "",
DevelopmentErrorsMode: false,
SocketReusePort: false,
HealthCheckPath: "",
FreeMemoryInterval: 10 * time.Second,
LogMemStats: false,
ResponseWriter: responsewriter.NewDefaultConfig(),
}
}
// LoadConfigFromEnv overrides current values with environment variables
func LoadConfigFromEnv(c *Config) (*Config, error) {
c = ensure.Ensure(c, NewDefaultConfig)
var port string
if err := env.String(&port, IMGPROXY_PORT); err != nil {
return nil, err
}
if len(port) > 0 {
c.Bind = fmt.Sprintf(":%s", port)
}
_, rwErr := responsewriter.LoadConfigFromEnv(&c.ResponseWriter)
err := errors.Join(
rwErr,
env.String(&c.Network, IMGPROXY_NETWORK),
env.String(&c.Bind, IMGPROXY_BIND),
env.URLPath(&c.PathPrefix, IMGPROXY_PATH_PREFIX),
env.Int(&c.MaxClients, IMGPROXY_MAX_CLIENTS),
env.Duration(&c.RequestTimeout, IMGPROXY_TIMEOUT),
env.Duration(&c.ReadRequestTimeout, IMGPROXY_READ_REQUEST_TIMEOUT),
env.Duration(&c.KeepAliveTimeout, IMGPROXY_KEEP_ALIVE_TIMEOUT),
env.Duration(&c.GracefulStopTimeout, IMGPROXY_GRACEFUL_STOP_TIMEOUT),
env.String(&c.CORSAllowOrigin, IMGPROXY_ALLOW_ORIGIN),
env.String(&c.Secret, IMGPROXY_SECRET),
env.Bool(&c.DevelopmentErrorsMode, IMGPROXY_DEVELOPMENT_ERRORS_MODE),
env.Bool(&c.SocketReusePort, IMGPROXY_SO_REUSEPORT),
env.URLPath(&c.HealthCheckPath, IMGPROXY_HEALTH_CHECK_PATH),
env.Duration(&c.FreeMemoryInterval, IMGPROXY_FREE_MEMORY_INTERVAL),
env.Bool(&c.LogMemStats, IMGPROXY_LOG_MEM_STATS),
)
return c, err
}
// Validate checks that the config values are valid
func (c *Config) Validate() error {
if len(c.Bind) == 0 {
return IMGPROXY_BIND.ErrorEmpty()
}
if c.MaxClients < 0 {
return IMGPROXY_MAX_CLIENTS.ErrorNegative()
}
if c.RequestTimeout <= 0 {
return IMGPROXY_TIMEOUT.ErrorZeroOrNegative()
}
if c.ReadRequestTimeout <= 0 {
return IMGPROXY_READ_REQUEST_TIMEOUT.ErrorZeroOrNegative()
}
if c.KeepAliveTimeout < 0 {
return IMGPROXY_KEEP_ALIVE_TIMEOUT.ErrorNegative()
}
if c.GracefulStopTimeout < 0 {
return IMGPROXY_GRACEFUL_STOP_TIMEOUT.ErrorNegative()
}
if c.FreeMemoryInterval <= 0 {
return IMGPROXY_FREE_MEMORY_INTERVAL.ErrorZeroOrNegative()
}
return nil
}