config.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package server
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "time"
  7. "github.com/imgproxy/imgproxy/v3/config"
  8. "github.com/imgproxy/imgproxy/v3/ensure"
  9. )
  10. const (
  11. // gracefulTimeout represents graceful shutdown timeout
  12. gracefulTimeout = time.Duration(5 * time.Second)
  13. )
  14. // Config represents HTTP server config
  15. type Config struct {
  16. Listen string // Address to listen on
  17. Network string // Network type (tcp, unix)
  18. Bind string // Bind address
  19. PathPrefix string // Path prefix for the server
  20. MaxClients int // Maximum number of concurrent clients
  21. ReadRequestTimeout time.Duration // Timeout for reading requests
  22. WriteResponseTimeout time.Duration // Timeout for writing responses
  23. KeepAliveTimeout time.Duration // Timeout for keep-alive connections
  24. GracefulTimeout time.Duration // Timeout for graceful shutdown
  25. CORSAllowOrigin string // CORS allowed origin
  26. Secret string // Secret for authorization
  27. DevelopmentErrorsMode bool // Enable development mode for detailed error messages
  28. SocketReusePort bool // Enable SO_REUSEPORT socket option
  29. HealthCheckPath string // Health check path from config
  30. FreeMemoryInterval time.Duration // Interval for freeing memory
  31. LogMemStats bool // Log memory stats
  32. }
  33. // NewDefaultConfig returns default config values
  34. func NewDefaultConfig() Config {
  35. return Config{
  36. Network: "tcp",
  37. Bind: ":8080",
  38. PathPrefix: "",
  39. MaxClients: 2048,
  40. ReadRequestTimeout: 10 * time.Second,
  41. KeepAliveTimeout: 10 * time.Second,
  42. WriteResponseTimeout: 10 * time.Second,
  43. GracefulTimeout: gracefulTimeout,
  44. CORSAllowOrigin: "",
  45. Secret: "",
  46. DevelopmentErrorsMode: false,
  47. SocketReusePort: false,
  48. HealthCheckPath: "",
  49. FreeMemoryInterval: 10 * time.Second,
  50. LogMemStats: false,
  51. }
  52. }
  53. // LoadConfigFromEnv overrides current values with environment variables
  54. func LoadConfigFromEnv(c *Config) (*Config, error) {
  55. c = ensure.Ensure(c, NewDefaultConfig)
  56. c.Network = config.Network
  57. c.Bind = config.Bind
  58. c.PathPrefix = config.PathPrefix
  59. c.MaxClients = config.MaxClients
  60. c.ReadRequestTimeout = time.Duration(config.ReadRequestTimeout) * time.Second
  61. c.KeepAliveTimeout = time.Duration(config.KeepAliveTimeout) * time.Second
  62. c.GracefulTimeout = gracefulTimeout
  63. c.CORSAllowOrigin = config.AllowOrigin
  64. c.Secret = config.Secret
  65. c.DevelopmentErrorsMode = config.DevelopmentErrorsMode
  66. c.SocketReusePort = config.SoReuseport
  67. c.HealthCheckPath = config.HealthCheckPath
  68. c.FreeMemoryInterval = time.Duration(config.FreeMemoryInterval) * time.Second
  69. c.LogMemStats = len(os.Getenv("IMGPROXY_LOG_MEM_STATS")) > 0
  70. return c, nil
  71. }
  72. // Validate checks that the config values are valid
  73. func (c *Config) Validate() error {
  74. if len(c.Bind) == 0 {
  75. return errors.New("bind address is not defined")
  76. }
  77. if c.MaxClients < 0 {
  78. return fmt.Errorf("max clients number should be greater than or equal 0, now - %d", c.MaxClients)
  79. }
  80. if c.ReadRequestTimeout <= 0 {
  81. return fmt.Errorf("read request timeout should be greater than 0, now - %d", c.ReadRequestTimeout)
  82. }
  83. if c.WriteResponseTimeout <= 0 {
  84. return fmt.Errorf("write response timeout should be greater than 0, now - %d", c.WriteResponseTimeout)
  85. }
  86. if c.KeepAliveTimeout < 0 {
  87. return fmt.Errorf("keep alive timeout should be greater than or equal to 0, now - %d", c.KeepAliveTimeout)
  88. }
  89. if c.GracefulTimeout < 0 {
  90. return fmt.Errorf("graceful timeout should be greater than or equal to 0, now - %d", c.GracefulTimeout)
  91. }
  92. if c.FreeMemoryInterval <= 0 {
  93. return errors.New("free memory interval should be greater than zero")
  94. }
  95. return nil
  96. }