config.go 17 KB

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