config.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. package config
  2. import (
  3. "flag"
  4. "fmt"
  5. "math"
  6. "os"
  7. "regexp"
  8. "runtime"
  9. log "github.com/sirupsen/logrus"
  10. "github.com/imgproxy/imgproxy/v3/config/configurators"
  11. "github.com/imgproxy/imgproxy/v3/imagetype"
  12. "github.com/imgproxy/imgproxy/v3/version"
  13. )
  14. var (
  15. Network string
  16. Bind string
  17. ReadTimeout int
  18. WriteTimeout int
  19. KeepAliveTimeout int
  20. DownloadTimeout int
  21. Concurrency int
  22. MaxClients int
  23. TTL int
  24. CacheControlPassthrough bool
  25. SetCanonicalHeader bool
  26. SoReuseport bool
  27. PathPrefix string
  28. MaxSrcResolution int
  29. MaxSrcFileSize int
  30. MaxAnimationFrames int
  31. MaxSvgCheckBytes int
  32. MaxRedirects int
  33. JpegProgressive bool
  34. PngInterlaced bool
  35. PngQuantize bool
  36. PngQuantizationColors int
  37. AvifSpeed int
  38. Quality int
  39. FormatQuality map[imagetype.Type]int
  40. StripMetadata bool
  41. KeepCopyright bool
  42. StripColorProfile bool
  43. AutoRotate bool
  44. EnforceThumbnail bool
  45. ReturnAttachment bool
  46. EnableWebpDetection bool
  47. EnforceWebp bool
  48. EnableAvifDetection bool
  49. EnforceAvif bool
  50. EnableClientHints bool
  51. PreferredFormats []imagetype.Type
  52. SkipProcessingFormats []imagetype.Type
  53. UseLinearColorspace bool
  54. DisableShrinkOnLoad bool
  55. Keys [][]byte
  56. Salts [][]byte
  57. SignatureSize int
  58. Secret string
  59. AllowOrigin string
  60. UserAgent string
  61. IgnoreSslVerification bool
  62. DevelopmentErrorsMode bool
  63. AllowedSources []*regexp.Regexp
  64. SanitizeSvg bool
  65. CookiePassthrough bool
  66. CookieBaseURL string
  67. LocalFileSystemRoot string
  68. S3Enabled bool
  69. S3Region string
  70. S3Endpoint string
  71. GCSEnabled bool
  72. GCSKey string
  73. GCSEndpoint string
  74. ABSEnabled bool
  75. ABSName string
  76. ABSKey string
  77. ABSEndpoint string
  78. SwiftEnabled bool
  79. SwiftUsername string
  80. SwiftAPIKey string
  81. SwiftAuthURL string
  82. SwiftDomain string
  83. SwiftTenant string
  84. SwiftAuthVersion int
  85. SwiftConnectTimeoutSeconds int
  86. SwiftTimeoutSeconds int
  87. ETagEnabled bool
  88. ETagBuster string
  89. BaseURL string
  90. Presets []string
  91. OnlyPresets bool
  92. WatermarkData string
  93. WatermarkPath string
  94. WatermarkURL string
  95. WatermarkOpacity float64
  96. FallbackImageData string
  97. FallbackImagePath string
  98. FallbackImageURL string
  99. FallbackImageHTTPCode int
  100. FallbackImageTTL int
  101. DataDogEnable bool
  102. NewRelicAppName string
  103. NewRelicKey string
  104. NewRelicLabels map[string]string
  105. PrometheusBind string
  106. PrometheusNamespace string
  107. BugsnagKey string
  108. BugsnagStage string
  109. HoneybadgerKey string
  110. HoneybadgerEnv string
  111. SentryDSN string
  112. SentryEnvironment string
  113. SentryRelease string
  114. AirbrakeProjecID int
  115. AirbrakeProjecKey string
  116. AirbrakeEnv string
  117. ReportDownloadingErrors bool
  118. EnableDebugHeaders bool
  119. FreeMemoryInterval int
  120. DownloadBufferSize int
  121. BufferPoolCalibrationThreshold int
  122. HealthCheckPath string
  123. )
  124. var (
  125. keyPath string
  126. saltPath string
  127. presetsPath string
  128. )
  129. func init() {
  130. Reset()
  131. flag.StringVar(&keyPath, "keypath", "", "path of the file with hex-encoded key")
  132. flag.StringVar(&saltPath, "saltpath", "", "path of the file with hex-encoded salt")
  133. flag.StringVar(&presetsPath, "presets", "", "path of the file with presets")
  134. }
  135. func Reset() {
  136. Network = "tcp"
  137. Bind = ":8080"
  138. ReadTimeout = 10
  139. WriteTimeout = 10
  140. KeepAliveTimeout = 10
  141. DownloadTimeout = 5
  142. Concurrency = runtime.NumCPU() * 2
  143. MaxClients = 0
  144. TTL = 3600
  145. CacheControlPassthrough = false
  146. SetCanonicalHeader = false
  147. SoReuseport = false
  148. PathPrefix = ""
  149. MaxSrcResolution = 16800000
  150. MaxSrcFileSize = 0
  151. MaxAnimationFrames = 1
  152. MaxSvgCheckBytes = 32 * 1024
  153. MaxRedirects = 10
  154. JpegProgressive = false
  155. PngInterlaced = false
  156. PngQuantize = false
  157. PngQuantizationColors = 256
  158. AvifSpeed = 5
  159. Quality = 80
  160. FormatQuality = map[imagetype.Type]int{imagetype.AVIF: 50}
  161. StripMetadata = true
  162. KeepCopyright = true
  163. StripColorProfile = true
  164. AutoRotate = true
  165. EnforceThumbnail = false
  166. ReturnAttachment = false
  167. EnableWebpDetection = false
  168. EnforceWebp = false
  169. EnableAvifDetection = false
  170. EnforceAvif = false
  171. EnableClientHints = false
  172. PreferredFormats = []imagetype.Type{
  173. imagetype.JPEG,
  174. imagetype.PNG,
  175. imagetype.GIF,
  176. imagetype.WEBP,
  177. imagetype.AVIF,
  178. imagetype.ICO,
  179. }
  180. SkipProcessingFormats = make([]imagetype.Type, 0)
  181. UseLinearColorspace = false
  182. DisableShrinkOnLoad = false
  183. Keys = make([][]byte, 0)
  184. Salts = make([][]byte, 0)
  185. SignatureSize = 32
  186. Secret = ""
  187. AllowOrigin = ""
  188. UserAgent = fmt.Sprintf("imgproxy/%s", version.Version())
  189. IgnoreSslVerification = false
  190. DevelopmentErrorsMode = false
  191. AllowedSources = make([]*regexp.Regexp, 0)
  192. SanitizeSvg = true
  193. CookiePassthrough = false
  194. CookieBaseURL = ""
  195. LocalFileSystemRoot = ""
  196. S3Enabled = false
  197. S3Region = ""
  198. S3Endpoint = ""
  199. GCSEnabled = false
  200. GCSKey = ""
  201. ABSEnabled = false
  202. ABSName = ""
  203. ABSKey = ""
  204. ABSEndpoint = ""
  205. SwiftEnabled = false
  206. SwiftUsername = ""
  207. SwiftAPIKey = ""
  208. SwiftAuthURL = ""
  209. SwiftAuthVersion = 0
  210. SwiftTenant = ""
  211. SwiftDomain = ""
  212. SwiftConnectTimeoutSeconds = 10
  213. SwiftTimeoutSeconds = 60
  214. ETagEnabled = false
  215. ETagBuster = ""
  216. BaseURL = ""
  217. Presets = make([]string, 0)
  218. OnlyPresets = false
  219. WatermarkData = ""
  220. WatermarkPath = ""
  221. WatermarkURL = ""
  222. WatermarkOpacity = 1
  223. FallbackImageData = ""
  224. FallbackImagePath = ""
  225. FallbackImageURL = ""
  226. FallbackImageHTTPCode = 200
  227. FallbackImageTTL = 0
  228. DataDogEnable = false
  229. NewRelicAppName = ""
  230. NewRelicKey = ""
  231. NewRelicLabels = make(map[string]string)
  232. PrometheusBind = ""
  233. PrometheusNamespace = ""
  234. BugsnagKey = ""
  235. BugsnagStage = "production"
  236. HoneybadgerKey = ""
  237. HoneybadgerEnv = "production"
  238. SentryDSN = ""
  239. SentryEnvironment = "production"
  240. SentryRelease = fmt.Sprintf("imgproxy@%s", version.Version())
  241. AirbrakeProjecID = 0
  242. AirbrakeProjecKey = ""
  243. AirbrakeEnv = "production"
  244. ReportDownloadingErrors = true
  245. EnableDebugHeaders = false
  246. FreeMemoryInterval = 10
  247. DownloadBufferSize = 0
  248. BufferPoolCalibrationThreshold = 1024
  249. HealthCheckPath = ""
  250. }
  251. func Configure() error {
  252. if port := os.Getenv("PORT"); len(port) > 0 {
  253. Bind = fmt.Sprintf(":%s", port)
  254. }
  255. configurators.String(&Network, "IMGPROXY_NETWORK")
  256. configurators.String(&Bind, "IMGPROXY_BIND")
  257. configurators.Int(&ReadTimeout, "IMGPROXY_READ_TIMEOUT")
  258. configurators.Int(&WriteTimeout, "IMGPROXY_WRITE_TIMEOUT")
  259. configurators.Int(&KeepAliveTimeout, "IMGPROXY_KEEP_ALIVE_TIMEOUT")
  260. configurators.Int(&DownloadTimeout, "IMGPROXY_DOWNLOAD_TIMEOUT")
  261. configurators.Int(&Concurrency, "IMGPROXY_CONCURRENCY")
  262. configurators.Int(&MaxClients, "IMGPROXY_MAX_CLIENTS")
  263. configurators.Int(&TTL, "IMGPROXY_TTL")
  264. configurators.Bool(&CacheControlPassthrough, "IMGPROXY_CACHE_CONTROL_PASSTHROUGH")
  265. configurators.Bool(&SetCanonicalHeader, "IMGPROXY_SET_CANONICAL_HEADER")
  266. configurators.Bool(&SoReuseport, "IMGPROXY_SO_REUSEPORT")
  267. configurators.String(&PathPrefix, "IMGPROXY_PATH_PREFIX")
  268. configurators.MegaInt(&MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION")
  269. configurators.Int(&MaxSrcFileSize, "IMGPROXY_MAX_SRC_FILE_SIZE")
  270. configurators.Int(&MaxSvgCheckBytes, "IMGPROXY_MAX_SVG_CHECK_BYTES")
  271. configurators.Int(&MaxAnimationFrames, "IMGPROXY_MAX_ANIMATION_FRAMES")
  272. configurators.Int(&MaxRedirects, "IMGPROXY_MAX_REDIRECTS")
  273. configurators.Patterns(&AllowedSources, "IMGPROXY_ALLOWED_SOURCES")
  274. configurators.Bool(&SanitizeSvg, "IMGPROXY_SANITIZE_SVG")
  275. configurators.Bool(&JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE")
  276. configurators.Bool(&PngInterlaced, "IMGPROXY_PNG_INTERLACED")
  277. configurators.Bool(&PngQuantize, "IMGPROXY_PNG_QUANTIZE")
  278. configurators.Int(&PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS")
  279. configurators.Int(&AvifSpeed, "IMGPROXY_AVIF_SPEED")
  280. configurators.Int(&Quality, "IMGPROXY_QUALITY")
  281. if err := configurators.ImageTypesQuality(FormatQuality, "IMGPROXY_FORMAT_QUALITY"); err != nil {
  282. return err
  283. }
  284. configurators.Bool(&StripMetadata, "IMGPROXY_STRIP_METADATA")
  285. configurators.Bool(&KeepCopyright, "IMGPROXY_KEEP_COPYRIGHT")
  286. configurators.Bool(&StripColorProfile, "IMGPROXY_STRIP_COLOR_PROFILE")
  287. configurators.Bool(&AutoRotate, "IMGPROXY_AUTO_ROTATE")
  288. configurators.Bool(&EnforceThumbnail, "IMGPROXY_ENFORCE_THUMBNAIL")
  289. configurators.Bool(&ReturnAttachment, "IMGPROXY_RETURN_ATTACHMENT")
  290. configurators.Bool(&EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION")
  291. configurators.Bool(&EnforceWebp, "IMGPROXY_ENFORCE_WEBP")
  292. configurators.Bool(&EnableAvifDetection, "IMGPROXY_ENABLE_AVIF_DETECTION")
  293. configurators.Bool(&EnforceAvif, "IMGPROXY_ENFORCE_AVIF")
  294. configurators.Bool(&EnableClientHints, "IMGPROXY_ENABLE_CLIENT_HINTS")
  295. configurators.String(&HealthCheckPath, "IMGPROXY_HEALTH_CHECK_PATH")
  296. if err := configurators.ImageTypes(&PreferredFormats, "IMGPROXY_PREFERRED_FORMATS"); err != nil {
  297. return err
  298. }
  299. if err := configurators.ImageTypes(&SkipProcessingFormats, "IMGPROXY_SKIP_PROCESSING_FORMATS"); err != nil {
  300. return err
  301. }
  302. configurators.Bool(&UseLinearColorspace, "IMGPROXY_USE_LINEAR_COLORSPACE")
  303. configurators.Bool(&DisableShrinkOnLoad, "IMGPROXY_DISABLE_SHRINK_ON_LOAD")
  304. if err := configurators.Hex(&Keys, "IMGPROXY_KEY"); err != nil {
  305. return err
  306. }
  307. if err := configurators.Hex(&Salts, "IMGPROXY_SALT"); err != nil {
  308. return err
  309. }
  310. configurators.Int(&SignatureSize, "IMGPROXY_SIGNATURE_SIZE")
  311. if err := configurators.HexFile(&Keys, keyPath); err != nil {
  312. return err
  313. }
  314. if err := configurators.HexFile(&Salts, saltPath); err != nil {
  315. return err
  316. }
  317. configurators.String(&Secret, "IMGPROXY_SECRET")
  318. configurators.String(&AllowOrigin, "IMGPROXY_ALLOW_ORIGIN")
  319. configurators.String(&UserAgent, "IMGPROXY_USER_AGENT")
  320. configurators.Bool(&IgnoreSslVerification, "IMGPROXY_IGNORE_SSL_VERIFICATION")
  321. configurators.Bool(&DevelopmentErrorsMode, "IMGPROXY_DEVELOPMENT_ERRORS_MODE")
  322. configurators.Bool(&CookiePassthrough, "IMGPROXY_COOKIE_PASSTHROUGH")
  323. configurators.String(&CookieBaseURL, "IMGPROXY_COOKIE_BASE_URL")
  324. configurators.String(&LocalFileSystemRoot, "IMGPROXY_LOCAL_FILESYSTEM_ROOT")
  325. configurators.Bool(&S3Enabled, "IMGPROXY_USE_S3")
  326. configurators.String(&S3Region, "IMGPROXY_S3_REGION")
  327. configurators.String(&S3Endpoint, "IMGPROXY_S3_ENDPOINT")
  328. configurators.Bool(&GCSEnabled, "IMGPROXY_USE_GCS")
  329. configurators.String(&GCSKey, "IMGPROXY_GCS_KEY")
  330. configurators.String(&GCSEndpoint, "IMGPROXY_GCS_ENDPOINT")
  331. configurators.Bool(&ABSEnabled, "IMGPROXY_USE_ABS")
  332. configurators.String(&ABSName, "IMGPROXY_ABS_NAME")
  333. configurators.String(&ABSKey, "IMGPROXY_ABS_KEY")
  334. configurators.String(&ABSEndpoint, "IMGPROXY_ABS_ENDPOINT")
  335. configurators.Bool(&SwiftEnabled, "IMGPROXY_USE_SWIFT")
  336. configurators.String(&SwiftUsername, "IMGPROXY_SWIFT_USERNAME")
  337. configurators.String(&SwiftAPIKey, "IMGPROXY_SWIFT_API_KEY")
  338. configurators.String(&SwiftAuthURL, "IMGPROXY_SWIFT_AUTH_URL")
  339. configurators.String(&SwiftDomain, "IMGPROXY_SWIFT_DOMAIN")
  340. configurators.String(&SwiftTenant, "IMGPROXY_SWIFT_TENANT")
  341. configurators.Int(&SwiftConnectTimeoutSeconds, "IMGPROXY_SWIFT_CONNECT_TIMEOUT_SECONDS")
  342. configurators.Int(&SwiftTimeoutSeconds, "IMGPROXY_SWIFT_TIMEOUT_SECONDS")
  343. configurators.Bool(&ETagEnabled, "IMGPROXY_USE_ETAG")
  344. configurators.String(&ETagBuster, "IMGPROXY_ETAG_BUSTER")
  345. configurators.String(&BaseURL, "IMGPROXY_BASE_URL")
  346. configurators.StringSlice(&Presets, "IMGPROXY_PRESETS")
  347. if err := configurators.StringSliceFile(&Presets, presetsPath); err != nil {
  348. return err
  349. }
  350. configurators.Bool(&OnlyPresets, "IMGPROXY_ONLY_PRESETS")
  351. configurators.String(&WatermarkData, "IMGPROXY_WATERMARK_DATA")
  352. configurators.String(&WatermarkPath, "IMGPROXY_WATERMARK_PATH")
  353. configurators.String(&WatermarkURL, "IMGPROXY_WATERMARK_URL")
  354. configurators.Float(&WatermarkOpacity, "IMGPROXY_WATERMARK_OPACITY")
  355. configurators.String(&FallbackImageData, "IMGPROXY_FALLBACK_IMAGE_DATA")
  356. configurators.String(&FallbackImagePath, "IMGPROXY_FALLBACK_IMAGE_PATH")
  357. configurators.String(&FallbackImageURL, "IMGPROXY_FALLBACK_IMAGE_URL")
  358. configurators.Int(&FallbackImageHTTPCode, "IMGPROXY_FALLBACK_IMAGE_HTTP_CODE")
  359. configurators.Int(&FallbackImageTTL, "IMGPROXY_FALLBACK_IMAGE_TTL")
  360. configurators.Bool(&DataDogEnable, "IMGPROXY_DATADOG_ENABLE")
  361. configurators.String(&NewRelicAppName, "IMGPROXY_NEW_RELIC_APP_NAME")
  362. configurators.String(&NewRelicKey, "IMGPROXY_NEW_RELIC_KEY")
  363. configurators.StringMap(&NewRelicLabels, "IMGPROXY_NEW_RELIC_LABELS")
  364. configurators.String(&PrometheusBind, "IMGPROXY_PROMETHEUS_BIND")
  365. configurators.String(&PrometheusNamespace, "IMGPROXY_PROMETHEUS_NAMESPACE")
  366. configurators.String(&BugsnagKey, "IMGPROXY_BUGSNAG_KEY")
  367. configurators.String(&BugsnagStage, "IMGPROXY_BUGSNAG_STAGE")
  368. configurators.String(&HoneybadgerKey, "IMGPROXY_HONEYBADGER_KEY")
  369. configurators.String(&HoneybadgerEnv, "IMGPROXY_HONEYBADGER_ENV")
  370. configurators.String(&SentryDSN, "IMGPROXY_SENTRY_DSN")
  371. configurators.String(&SentryEnvironment, "IMGPROXY_SENTRY_ENVIRONMENT")
  372. configurators.String(&SentryRelease, "IMGPROXY_SENTRY_RELEASE")
  373. configurators.Int(&AirbrakeProjecID, "IMGPROXY_AIRBRAKE_PROJECT_ID")
  374. configurators.String(&AirbrakeProjecKey, "IMGPROXY_AIRBRAKE_PROJECT_KEY")
  375. configurators.String(&AirbrakeEnv, "IMGPROXY_AIRBRAKE_ENVIRONMENT")
  376. configurators.Bool(&ReportDownloadingErrors, "IMGPROXY_REPORT_DOWNLOADING_ERRORS")
  377. configurators.Bool(&EnableDebugHeaders, "IMGPROXY_ENABLE_DEBUG_HEADERS")
  378. configurators.Int(&FreeMemoryInterval, "IMGPROXY_FREE_MEMORY_INTERVAL")
  379. configurators.Int(&DownloadBufferSize, "IMGPROXY_DOWNLOAD_BUFFER_SIZE")
  380. configurators.Int(&BufferPoolCalibrationThreshold, "IMGPROXY_BUFFER_POOL_CALIBRATION_THRESHOLD")
  381. if len(Keys) != len(Salts) {
  382. return fmt.Errorf("Number of keys and number of salts should be equal. Keys: %d, salts: %d", len(Keys), len(Salts))
  383. }
  384. if len(Keys) == 0 {
  385. log.Warning("No keys defined, so signature checking is disabled")
  386. }
  387. if len(Salts) == 0 {
  388. log.Warning("No salts defined, so signature checking is disabled")
  389. }
  390. if SignatureSize < 1 || SignatureSize > 32 {
  391. return fmt.Errorf("Signature size should be within 1 and 32, now - %d\n", SignatureSize)
  392. }
  393. if len(Bind) == 0 {
  394. return fmt.Errorf("Bind address is not defined")
  395. }
  396. if ReadTimeout <= 0 {
  397. return fmt.Errorf("Read timeout should be greater than 0, now - %d\n", ReadTimeout)
  398. }
  399. if WriteTimeout <= 0 {
  400. return fmt.Errorf("Write timeout should be greater than 0, now - %d\n", WriteTimeout)
  401. }
  402. if KeepAliveTimeout < 0 {
  403. return fmt.Errorf("KeepAlive timeout should be greater than or equal to 0, now - %d\n", KeepAliveTimeout)
  404. }
  405. if DownloadTimeout <= 0 {
  406. return fmt.Errorf("Download timeout should be greater than 0, now - %d\n", DownloadTimeout)
  407. }
  408. if Concurrency <= 0 {
  409. return fmt.Errorf("Concurrency should be greater than 0, now - %d\n", Concurrency)
  410. }
  411. if MaxClients <= 0 {
  412. MaxClients = Concurrency * 10
  413. }
  414. if TTL <= 0 {
  415. return fmt.Errorf("TTL should be greater than 0, now - %d\n", TTL)
  416. }
  417. if MaxSrcResolution <= 0 {
  418. return fmt.Errorf("Max src resolution should be greater than 0, now - %d\n", MaxSrcResolution)
  419. }
  420. if MaxSrcFileSize < 0 {
  421. return fmt.Errorf("Max src file size should be greater than or equal to 0, now - %d\n", MaxSrcFileSize)
  422. }
  423. if MaxAnimationFrames <= 0 {
  424. return fmt.Errorf("Max animation frames should be greater than 0, now - %d\n", MaxAnimationFrames)
  425. }
  426. if PngQuantizationColors < 2 {
  427. return fmt.Errorf("Png quantization colors should be greater than 1, now - %d\n", PngQuantizationColors)
  428. } else if PngQuantizationColors > 256 {
  429. return fmt.Errorf("Png quantization colors can't be greater than 256, now - %d\n", PngQuantizationColors)
  430. }
  431. if AvifSpeed < 0 {
  432. return fmt.Errorf("Avif speed should be greater than 0, now - %d\n", AvifSpeed)
  433. } else if AvifSpeed > 8 {
  434. return fmt.Errorf("Avif speed can't be greater than 8, now - %d\n", AvifSpeed)
  435. }
  436. if Quality <= 0 {
  437. return fmt.Errorf("Quality should be greater than 0, now - %d\n", Quality)
  438. } else if Quality > 100 {
  439. return fmt.Errorf("Quality can't be greater than 100, now - %d\n", Quality)
  440. }
  441. if len(PreferredFormats) == 0 {
  442. return fmt.Errorf("At least one preferred format should be specified")
  443. }
  444. if IgnoreSslVerification {
  445. log.Warning("Ignoring SSL verification is very unsafe")
  446. }
  447. if LocalFileSystemRoot != "" {
  448. stat, err := os.Stat(LocalFileSystemRoot)
  449. if err != nil {
  450. return fmt.Errorf("Cannot use local directory: %s", err)
  451. }
  452. if !stat.IsDir() {
  453. return fmt.Errorf("Cannot use local directory: not a directory")
  454. }
  455. if LocalFileSystemRoot == "/" {
  456. log.Warning("Exposing root via IMGPROXY_LOCAL_FILESYSTEM_ROOT is unsafe")
  457. }
  458. }
  459. if _, ok := os.LookupEnv("IMGPROXY_USE_GCS"); !ok && len(GCSKey) > 0 {
  460. log.Warning("Set IMGPROXY_USE_GCS to true since it may be required by future versions to enable GCS support")
  461. GCSEnabled = true
  462. }
  463. if WatermarkOpacity <= 0 {
  464. return fmt.Errorf("Watermark opacity should be greater than 0")
  465. } else if WatermarkOpacity > 1 {
  466. return fmt.Errorf("Watermark opacity should be less than or equal to 1")
  467. }
  468. if FallbackImageHTTPCode < 100 || FallbackImageHTTPCode > 599 {
  469. return fmt.Errorf("Fallback image HTTP code should be between 100 and 599")
  470. }
  471. if len(PrometheusBind) > 0 && PrometheusBind == Bind {
  472. return fmt.Errorf("Can't use the same binding for the main server and Prometheus")
  473. }
  474. if FreeMemoryInterval <= 0 {
  475. return fmt.Errorf("Free memory interval should be greater than zero")
  476. }
  477. if DownloadBufferSize < 0 {
  478. return fmt.Errorf("Download buffer size should be greater than or equal to 0")
  479. } else if DownloadBufferSize > math.MaxInt32 {
  480. return fmt.Errorf("Download buffer size can't be greater than %d", math.MaxInt32)
  481. }
  482. if BufferPoolCalibrationThreshold < 64 {
  483. return fmt.Errorf("Buffer pool calibration threshold should be greater than or equal to 64")
  484. }
  485. return nil
  486. }