1
0

config.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package optionsparser
  2. import (
  3. "errors"
  4. "os"
  5. "github.com/imgproxy/imgproxy/v3/ensure"
  6. "github.com/imgproxy/imgproxy/v3/env"
  7. )
  8. type URLReplacement = env.URLReplacement
  9. const (
  10. PresetsFlagName = "presets" // --presets flag name
  11. )
  12. var (
  13. IMGPROXY_PRESETS_SEPARATOR = env.Describe("IMGPROXY_PRESETS_SEPARATOR", "string")
  14. IMGPROXY_PRESETS = env.Describe("IMGPROXY_PRESETS", "separated list of strings (see IMGPROXY_PRESETS_SEPARATOR)")
  15. IMGPROXY_ONLY_PRESETS = env.Describe("IMGPROXY_ONLY_PRESETS", "boolean")
  16. IMGPROXY_ALLOWED_PROCESSING_OPTIONS = env.Describe("IMGPROXY_ALLOWED_PROCESSING_OPTIONS", "comma-separated list of strings")
  17. IMGPROXY_ALLOW_SECURITY_OPTIONS = env.Describe("IMGPROXY_ALLOW_SECURITY_OPTIONS", "boolean")
  18. IMGPROXY_AUTO_WEBP = env.Describe("IMGPROXY_AUTO_WEBP", "boolean")
  19. IMGPROXY_ENFORCE_WEBP = env.Describe("IMGPROXY_ENFORCE_WEBP", "boolean")
  20. IMGPROXY_AUTO_AVIF = env.Describe("IMGPROXY_AUTO_AVIF", "boolean")
  21. IMGPROXY_ENFORCE_AVIF = env.Describe("IMGPROXY_ENFORCE_AVIF", "boolean")
  22. IMGPROXY_AUTO_JXL = env.Describe("IMGPROXY_AUTO_JXL", "boolean")
  23. IMGPROXY_ENFORCE_JXL = env.Describe("IMGPROXY_ENFORCE_JXL", "boolean")
  24. IMGPROXY_ENABLE_CLIENT_HINTS = env.Describe("IMGPROXY_ENABLE_CLIENT_HINTS", "boolean")
  25. IMGPROXY_ARGUMENTS_SEPARATOR = env.Describe("IMGPROXY_ARGUMENTS_SEPARATOR", "string")
  26. IMGPROXY_BASE_URL = env.Describe("IMGPROXY_BASE_URL", "string")
  27. IMGPROXY_URL_REPLACEMENTS = env.Describe("IMGPROXY_URL_REPLACEMENTS", "comma-separated list of key=value pairs")
  28. IMGPROXY_BASE64_URL_INCLUDES_FILENAME = env.Describe("IMGPROXY_BASE64_URL_INCLUDES_FILENAME", "boolean")
  29. // Artificial env.desc for --presets flag
  30. PRESETS_PATH = env.Describe("--"+PresetsFlagName, "path to presets file")
  31. )
  32. // Config represents the configuration for options processing
  33. type Config struct {
  34. // Presets configuration
  35. Presets []string // Available presets
  36. OnlyPresets bool // Whether to allow only presets
  37. // Security and validation
  38. AllowedProcessingOptions []string // List of allowed processing options
  39. AllowSecurityOptions bool // Whether to allow security options in URLs
  40. // Format preference and enforcement
  41. AutoWebp bool // Whether to automatically serve WebP when supported
  42. EnforceWebp bool // Whether to enforce WebP format
  43. AutoAvif bool // Whether to automatically serve AVIF when supported
  44. EnforceAvif bool // Whether to enforce AVIF format
  45. AutoJxl bool // Whether to automatically serve JXL when supported
  46. EnforceJxl bool // Whether to enforce JXL format
  47. // Client hints
  48. EnableClientHints bool // Whether to enable client hints support
  49. // URL processing
  50. ArgumentsSeparator string // Separator for URL arguments
  51. BaseURL string // Base URL for relative URLs
  52. URLReplacements []URLReplacement // URL replacement rules
  53. Base64URLIncludesFilename bool // Whether base64 URLs include filename
  54. }
  55. // NewDefaultConfig creates a new default configuration for options processing
  56. func NewDefaultConfig() Config {
  57. return Config{
  58. // Presets configuration
  59. OnlyPresets: false,
  60. // Security and validation
  61. AllowSecurityOptions: false,
  62. // Format preference and enforcement (copied from global config defaults)
  63. AutoWebp: false,
  64. EnforceWebp: false,
  65. AutoAvif: false,
  66. EnforceAvif: false,
  67. AutoJxl: false,
  68. EnforceJxl: false,
  69. // Client hints
  70. EnableClientHints: false,
  71. // URL processing (copied from global config defaults)
  72. ArgumentsSeparator: ":",
  73. BaseURL: "",
  74. Base64URLIncludesFilename: false,
  75. }
  76. }
  77. // LoadConfigFromEnv loads configuration from global config variables
  78. func LoadConfigFromEnv(c *Config) (*Config, error) {
  79. c = ensure.Ensure(c, NewDefaultConfig)
  80. sep := ","
  81. var presetsPath string
  82. // NOTE: Here is the workaround for reading --presets flag from CLI.
  83. // Otherwise, we'd have to either store it in a global variable or
  84. // pass cli.Command down the call stack.
  85. for i, arg := range os.Args {
  86. if arg == "--"+PresetsFlagName && i+1 < len(os.Args) {
  87. presetsPath = os.Args[i+1]
  88. break
  89. }
  90. }
  91. c.Presets = make([]string, 0)
  92. c.URLReplacements = make([]URLReplacement, 0)
  93. err := errors.Join(
  94. env.String(&sep, IMGPROXY_PRESETS_SEPARATOR),
  95. env.StringSliceSep(&c.Presets, IMGPROXY_PRESETS, sep),
  96. env.Bool(&c.OnlyPresets, IMGPROXY_ONLY_PRESETS),
  97. // Security and validation
  98. env.StringSlice(&c.AllowedProcessingOptions, IMGPROXY_ALLOWED_PROCESSING_OPTIONS),
  99. env.Bool(&c.AllowSecurityOptions, IMGPROXY_ALLOW_SECURITY_OPTIONS),
  100. // Format preference and enforcement
  101. env.Bool(&c.AutoWebp, IMGPROXY_AUTO_WEBP),
  102. env.Bool(&c.EnforceWebp, IMGPROXY_ENFORCE_WEBP),
  103. env.Bool(&c.AutoAvif, IMGPROXY_AUTO_AVIF),
  104. env.Bool(&c.EnforceAvif, IMGPROXY_ENFORCE_AVIF),
  105. env.Bool(&c.AutoJxl, IMGPROXY_AUTO_JXL),
  106. env.Bool(&c.EnforceJxl, IMGPROXY_ENFORCE_JXL),
  107. // Client hints
  108. env.Bool(&c.EnableClientHints, IMGPROXY_ENABLE_CLIENT_HINTS),
  109. // URL processing
  110. env.String(&c.ArgumentsSeparator, IMGPROXY_ARGUMENTS_SEPARATOR),
  111. env.String(&c.BaseURL, IMGPROXY_BASE_URL),
  112. env.Bool(&c.Base64URLIncludesFilename, IMGPROXY_BASE64_URL_INCLUDES_FILENAME),
  113. env.StringSliceFile(&c.Presets, PRESETS_PATH, presetsPath),
  114. env.URLReplacements(&c.URLReplacements, IMGPROXY_URL_REPLACEMENTS),
  115. )
  116. return c, err
  117. }
  118. // Validate validates the configuration values
  119. func (c *Config) Validate() error {
  120. // Arguments separator validation
  121. if c.ArgumentsSeparator == "" {
  122. return IMGPROXY_ARGUMENTS_SEPARATOR.ErrorEmpty()
  123. }
  124. return nil
  125. }