config.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. package main
  2. import (
  3. "bufio"
  4. "encoding/hex"
  5. "flag"
  6. "fmt"
  7. "math"
  8. "os"
  9. "runtime"
  10. "strconv"
  11. "strings"
  12. )
  13. func intEnvConfig(i *int, name string) {
  14. if env, err := strconv.Atoi(os.Getenv(name)); err == nil {
  15. *i = env
  16. }
  17. }
  18. func floatEnvConfig(i *float64, name string) {
  19. if env, err := strconv.ParseFloat(os.Getenv(name), 64); err == nil {
  20. *i = env
  21. }
  22. }
  23. func megaIntEnvConfig(f *int, name string) {
  24. if env, err := strconv.ParseFloat(os.Getenv(name), 64); err == nil {
  25. *f = int(env * 1000000)
  26. }
  27. }
  28. func strEnvConfig(s *string, name string) {
  29. if env := os.Getenv(name); len(env) > 0 {
  30. *s = env
  31. }
  32. }
  33. func strSliceEnvConfig(s *[]string, name string) {
  34. if env := os.Getenv(name); len(env) > 0 {
  35. parts := strings.Split(env, ",")
  36. for i, p := range parts {
  37. parts[i] = strings.TrimSpace(p)
  38. }
  39. *s = parts
  40. return
  41. }
  42. *s = []string{}
  43. }
  44. func boolEnvConfig(b *bool, name string) {
  45. if env, err := strconv.ParseBool(os.Getenv(name)); err == nil {
  46. *b = env
  47. }
  48. }
  49. func imageTypesEnvConfig(it *[]imageType, name string) {
  50. *it = []imageType{}
  51. if env := os.Getenv(name); len(env) > 0 {
  52. parts := strings.Split(env, ",")
  53. for _, p := range parts {
  54. pt := strings.TrimSpace(p)
  55. if t, ok := imageTypes[pt]; ok {
  56. *it = append(*it, t)
  57. } else {
  58. logWarning("Unknown image format to skip: %s", pt)
  59. }
  60. }
  61. }
  62. }
  63. func hexEnvConfig(b *[]securityKey, name string) error {
  64. var err error
  65. if env := os.Getenv(name); len(env) > 0 {
  66. parts := strings.Split(env, ",")
  67. keys := make([]securityKey, len(parts))
  68. for i, part := range parts {
  69. if keys[i], err = hex.DecodeString(part); err != nil {
  70. return fmt.Errorf("%s expected to be hex-encoded strings. Invalid: %s\n", name, part)
  71. }
  72. }
  73. *b = keys
  74. }
  75. return nil
  76. }
  77. func hexFileConfig(b *[]securityKey, filepath string) error {
  78. if len(filepath) == 0 {
  79. return nil
  80. }
  81. f, err := os.Open(filepath)
  82. if err != nil {
  83. return fmt.Errorf("Can't open file %s\n", filepath)
  84. }
  85. keys := []securityKey{}
  86. scanner := bufio.NewScanner(f)
  87. for scanner.Scan() {
  88. part := scanner.Text()
  89. if len(part) == 0 {
  90. continue
  91. }
  92. if key, err := hex.DecodeString(part); err == nil {
  93. keys = append(keys, key)
  94. } else {
  95. return fmt.Errorf("%s expected to contain hex-encoded strings. Invalid: %s\n", filepath, part)
  96. }
  97. }
  98. if err := scanner.Err(); err != nil {
  99. return fmt.Errorf("Failed to read file %s: %s", filepath, err)
  100. }
  101. *b = keys
  102. return nil
  103. }
  104. func presetEnvConfig(p presets, name string) error {
  105. if env := os.Getenv(name); len(env) > 0 {
  106. presetStrings := strings.Split(env, ",")
  107. for _, presetStr := range presetStrings {
  108. if err := parsePreset(p, presetStr); err != nil {
  109. return fmt.Errorf(err.Error())
  110. }
  111. }
  112. }
  113. return nil
  114. }
  115. func presetFileConfig(p presets, filepath string) error {
  116. if len(filepath) == 0 {
  117. return nil
  118. }
  119. f, err := os.Open(filepath)
  120. if err != nil {
  121. return fmt.Errorf("Can't open file %s\n", filepath)
  122. }
  123. scanner := bufio.NewScanner(f)
  124. for scanner.Scan() {
  125. if err := parsePreset(p, scanner.Text()); err != nil {
  126. return fmt.Errorf(err.Error())
  127. }
  128. }
  129. if err := scanner.Err(); err != nil {
  130. return fmt.Errorf("Failed to read presets file: %s", err)
  131. }
  132. return nil
  133. }
  134. type config struct {
  135. Network string
  136. Bind string
  137. ReadTimeout int
  138. WriteTimeout int
  139. KeepAliveTimeout int
  140. DownloadTimeout int
  141. Concurrency int
  142. MaxClients int
  143. TTL int
  144. CacheControlPassthrough bool
  145. SoReuseport bool
  146. PathPrefix string
  147. MaxSrcDimension int
  148. MaxSrcResolution int
  149. MaxSrcFileSize int
  150. MaxAnimationFrames int
  151. MaxSvgCheckBytes int
  152. JpegProgressive bool
  153. PngInterlaced bool
  154. PngQuantize bool
  155. PngQuantizationColors int
  156. Quality int
  157. GZipCompression int
  158. StripMetadata bool
  159. EnableWebpDetection bool
  160. EnforceWebp bool
  161. EnableClientHints bool
  162. SkipProcessingFormats []imageType
  163. UseLinearColorspace bool
  164. DisableShrinkOnLoad bool
  165. Keys []securityKey
  166. Salts []securityKey
  167. AllowInsecure bool
  168. SignatureSize int
  169. Secret string
  170. AllowOrigin string
  171. UserAgent string
  172. IgnoreSslVerification bool
  173. DevelopmentErrorsMode bool
  174. AllowedSources []string
  175. LocalFileSystemRoot string
  176. S3Enabled bool
  177. S3Region string
  178. S3Endpoint string
  179. GCSEnabled bool
  180. GCSKey string
  181. ETagEnabled bool
  182. BaseURL string
  183. Presets presets
  184. OnlyPresets bool
  185. WatermarkData string
  186. WatermarkPath string
  187. WatermarkURL string
  188. WatermarkOpacity float64
  189. FallbackImageData string
  190. FallbackImagePath string
  191. FallbackImageURL string
  192. NewRelicAppName string
  193. NewRelicKey string
  194. PrometheusBind string
  195. PrometheusNamespace string
  196. BugsnagKey string
  197. BugsnagStage string
  198. HoneybadgerKey string
  199. HoneybadgerEnv string
  200. SentryDSN string
  201. SentryEnvironment string
  202. SentryRelease string
  203. ReportDownloadingErrors bool
  204. FreeMemoryInterval int
  205. DownloadBufferSize int
  206. GZipBufferSize int
  207. BufferPoolCalibrationThreshold int
  208. }
  209. var conf = config{
  210. Network: "tcp",
  211. Bind: ":8080",
  212. ReadTimeout: 10,
  213. WriteTimeout: 10,
  214. KeepAliveTimeout: 10,
  215. DownloadTimeout: 5,
  216. Concurrency: runtime.NumCPU() * 2,
  217. TTL: 3600,
  218. MaxSrcResolution: 16800000,
  219. MaxAnimationFrames: 1,
  220. MaxSvgCheckBytes: 32 * 1024,
  221. SignatureSize: 32,
  222. PngQuantizationColors: 256,
  223. Quality: 80,
  224. StripMetadata: true,
  225. UserAgent: fmt.Sprintf("imgproxy/%s", version),
  226. Presets: make(presets),
  227. WatermarkOpacity: 1,
  228. BugsnagStage: "production",
  229. HoneybadgerEnv: "production",
  230. SentryEnvironment: "production",
  231. SentryRelease: fmt.Sprintf("imgproxy/%s", version),
  232. ReportDownloadingErrors: true,
  233. FreeMemoryInterval: 10,
  234. BufferPoolCalibrationThreshold: 1024,
  235. }
  236. func configure() error {
  237. keyPath := flag.String("keypath", "", "path of the file with hex-encoded key")
  238. saltPath := flag.String("saltpath", "", "path of the file with hex-encoded salt")
  239. presetsPath := flag.String("presets", "", "path of the file with presets")
  240. flag.Parse()
  241. if port := os.Getenv("PORT"); len(port) > 0 {
  242. conf.Bind = fmt.Sprintf(":%s", port)
  243. }
  244. strEnvConfig(&conf.Network, "IMGPROXY_NETWORK")
  245. strEnvConfig(&conf.Bind, "IMGPROXY_BIND")
  246. intEnvConfig(&conf.ReadTimeout, "IMGPROXY_READ_TIMEOUT")
  247. intEnvConfig(&conf.WriteTimeout, "IMGPROXY_WRITE_TIMEOUT")
  248. intEnvConfig(&conf.KeepAliveTimeout, "IMGPROXY_KEEP_ALIVE_TIMEOUT")
  249. intEnvConfig(&conf.DownloadTimeout, "IMGPROXY_DOWNLOAD_TIMEOUT")
  250. intEnvConfig(&conf.Concurrency, "IMGPROXY_CONCURRENCY")
  251. intEnvConfig(&conf.MaxClients, "IMGPROXY_MAX_CLIENTS")
  252. intEnvConfig(&conf.TTL, "IMGPROXY_TTL")
  253. boolEnvConfig(&conf.CacheControlPassthrough, "IMGPROXY_CACHE_CONTROL_PASSTHROUGH")
  254. boolEnvConfig(&conf.SoReuseport, "IMGPROXY_SO_REUSEPORT")
  255. strEnvConfig(&conf.PathPrefix, "IMGPROXY_PATH_PREFIX")
  256. intEnvConfig(&conf.MaxSrcDimension, "IMGPROXY_MAX_SRC_DIMENSION")
  257. megaIntEnvConfig(&conf.MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION")
  258. intEnvConfig(&conf.MaxSrcFileSize, "IMGPROXY_MAX_SRC_FILE_SIZE")
  259. intEnvConfig(&conf.MaxSvgCheckBytes, "IMGPROXY_MAX_SVG_CHECK_BYTES")
  260. if _, ok := os.LookupEnv("IMGPROXY_MAX_GIF_FRAMES"); ok {
  261. logWarning("`IMGPROXY_MAX_GIF_FRAMES` is deprecated and will be removed in future versions. Use `IMGPROXY_MAX_ANIMATION_FRAMES` instead")
  262. intEnvConfig(&conf.MaxAnimationFrames, "IMGPROXY_MAX_GIF_FRAMES")
  263. }
  264. intEnvConfig(&conf.MaxAnimationFrames, "IMGPROXY_MAX_ANIMATION_FRAMES")
  265. strSliceEnvConfig(&conf.AllowedSources, "IMGPROXY_ALLOWED_SOURCES")
  266. boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE")
  267. boolEnvConfig(&conf.PngInterlaced, "IMGPROXY_PNG_INTERLACED")
  268. boolEnvConfig(&conf.PngQuantize, "IMGPROXY_PNG_QUANTIZE")
  269. intEnvConfig(&conf.PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS")
  270. intEnvConfig(&conf.Quality, "IMGPROXY_QUALITY")
  271. intEnvConfig(&conf.GZipCompression, "IMGPROXY_GZIP_COMPRESSION")
  272. boolEnvConfig(&conf.StripMetadata, "IMGPROXY_STRIP_METADATA")
  273. boolEnvConfig(&conf.EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION")
  274. boolEnvConfig(&conf.EnforceWebp, "IMGPROXY_ENFORCE_WEBP")
  275. boolEnvConfig(&conf.EnableClientHints, "IMGPROXY_ENABLE_CLIENT_HINTS")
  276. imageTypesEnvConfig(&conf.SkipProcessingFormats, "IMGPROXY_SKIP_PROCESSING_FORMATS")
  277. boolEnvConfig(&conf.UseLinearColorspace, "IMGPROXY_USE_LINEAR_COLORSPACE")
  278. boolEnvConfig(&conf.DisableShrinkOnLoad, "IMGPROXY_DISABLE_SHRINK_ON_LOAD")
  279. if err := hexEnvConfig(&conf.Keys, "IMGPROXY_KEY"); err != nil {
  280. return err
  281. }
  282. if err := hexEnvConfig(&conf.Salts, "IMGPROXY_SALT"); err != nil {
  283. return err
  284. }
  285. intEnvConfig(&conf.SignatureSize, "IMGPROXY_SIGNATURE_SIZE")
  286. if err := hexFileConfig(&conf.Keys, *keyPath); err != nil {
  287. return err
  288. }
  289. if err := hexFileConfig(&conf.Salts, *saltPath); err != nil {
  290. return err
  291. }
  292. strEnvConfig(&conf.Secret, "IMGPROXY_SECRET")
  293. strEnvConfig(&conf.AllowOrigin, "IMGPROXY_ALLOW_ORIGIN")
  294. strEnvConfig(&conf.UserAgent, "IMGPROXY_USER_AGENT")
  295. boolEnvConfig(&conf.IgnoreSslVerification, "IMGPROXY_IGNORE_SSL_VERIFICATION")
  296. boolEnvConfig(&conf.DevelopmentErrorsMode, "IMGPROXY_DEVELOPMENT_ERRORS_MODE")
  297. strEnvConfig(&conf.LocalFileSystemRoot, "IMGPROXY_LOCAL_FILESYSTEM_ROOT")
  298. boolEnvConfig(&conf.S3Enabled, "IMGPROXY_USE_S3")
  299. strEnvConfig(&conf.S3Region, "IMGPROXY_S3_REGION")
  300. strEnvConfig(&conf.S3Endpoint, "IMGPROXY_S3_ENDPOINT")
  301. boolEnvConfig(&conf.GCSEnabled, "IMGPROXY_USE_GCS")
  302. strEnvConfig(&conf.GCSKey, "IMGPROXY_GCS_KEY")
  303. boolEnvConfig(&conf.ETagEnabled, "IMGPROXY_USE_ETAG")
  304. strEnvConfig(&conf.BaseURL, "IMGPROXY_BASE_URL")
  305. if err := presetEnvConfig(conf.Presets, "IMGPROXY_PRESETS"); err != nil {
  306. return err
  307. }
  308. if err := presetFileConfig(conf.Presets, *presetsPath); err != nil {
  309. return err
  310. }
  311. boolEnvConfig(&conf.OnlyPresets, "IMGPROXY_ONLY_PRESETS")
  312. strEnvConfig(&conf.WatermarkData, "IMGPROXY_WATERMARK_DATA")
  313. strEnvConfig(&conf.WatermarkPath, "IMGPROXY_WATERMARK_PATH")
  314. strEnvConfig(&conf.WatermarkURL, "IMGPROXY_WATERMARK_URL")
  315. floatEnvConfig(&conf.WatermarkOpacity, "IMGPROXY_WATERMARK_OPACITY")
  316. strEnvConfig(&conf.FallbackImageData, "IMGPROXY_FALLBACK_IMAGE_DATA")
  317. strEnvConfig(&conf.FallbackImagePath, "IMGPROXY_FALLBACK_IMAGE_PATH")
  318. strEnvConfig(&conf.FallbackImageURL, "IMGPROXY_FALLBACK_IMAGE_URL")
  319. strEnvConfig(&conf.NewRelicAppName, "IMGPROXY_NEW_RELIC_APP_NAME")
  320. strEnvConfig(&conf.NewRelicKey, "IMGPROXY_NEW_RELIC_KEY")
  321. strEnvConfig(&conf.PrometheusBind, "IMGPROXY_PROMETHEUS_BIND")
  322. strEnvConfig(&conf.PrometheusNamespace, "IMGPROXY_PROMETHEUS_NAMESPACE")
  323. strEnvConfig(&conf.BugsnagKey, "IMGPROXY_BUGSNAG_KEY")
  324. strEnvConfig(&conf.BugsnagStage, "IMGPROXY_BUGSNAG_STAGE")
  325. strEnvConfig(&conf.HoneybadgerKey, "IMGPROXY_HONEYBADGER_KEY")
  326. strEnvConfig(&conf.HoneybadgerEnv, "IMGPROXY_HONEYBADGER_ENV")
  327. strEnvConfig(&conf.SentryDSN, "IMGPROXY_SENTRY_DSN")
  328. strEnvConfig(&conf.SentryEnvironment, "IMGPROXY_SENTRY_ENVIRONMENT")
  329. strEnvConfig(&conf.SentryRelease, "IMGPROXY_SENTRY_RELEASE")
  330. boolEnvConfig(&conf.ReportDownloadingErrors, "IMGPROXY_REPORT_DOWNLOADING_ERRORS")
  331. intEnvConfig(&conf.FreeMemoryInterval, "IMGPROXY_FREE_MEMORY_INTERVAL")
  332. intEnvConfig(&conf.DownloadBufferSize, "IMGPROXY_DOWNLOAD_BUFFER_SIZE")
  333. intEnvConfig(&conf.GZipBufferSize, "IMGPROXY_GZIP_BUFFER_SIZE")
  334. intEnvConfig(&conf.BufferPoolCalibrationThreshold, "IMGPROXY_BUFFER_POOL_CALIBRATION_THRESHOLD")
  335. if len(conf.Keys) != len(conf.Salts) {
  336. return fmt.Errorf("Number of keys and number of salts should be equal. Keys: %d, salts: %d", len(conf.Keys), len(conf.Salts))
  337. }
  338. if len(conf.Keys) == 0 {
  339. logWarning("No keys defined, so signature checking is disabled")
  340. conf.AllowInsecure = true
  341. }
  342. if len(conf.Salts) == 0 {
  343. logWarning("No salts defined, so signature checking is disabled")
  344. conf.AllowInsecure = true
  345. }
  346. if conf.SignatureSize < 1 || conf.SignatureSize > 32 {
  347. return fmt.Errorf("Signature size should be within 1 and 32, now - %d\n", conf.SignatureSize)
  348. }
  349. if len(conf.Bind) == 0 {
  350. return fmt.Errorf("Bind address is not defined")
  351. }
  352. if conf.ReadTimeout <= 0 {
  353. return fmt.Errorf("Read timeout should be greater than 0, now - %d\n", conf.ReadTimeout)
  354. }
  355. if conf.WriteTimeout <= 0 {
  356. return fmt.Errorf("Write timeout should be greater than 0, now - %d\n", conf.WriteTimeout)
  357. }
  358. if conf.KeepAliveTimeout < 0 {
  359. return fmt.Errorf("KeepAlive timeout should be greater than or equal to 0, now - %d\n", conf.KeepAliveTimeout)
  360. }
  361. if conf.DownloadTimeout <= 0 {
  362. return fmt.Errorf("Download timeout should be greater than 0, now - %d\n", conf.DownloadTimeout)
  363. }
  364. if conf.Concurrency <= 0 {
  365. return fmt.Errorf("Concurrency should be greater than 0, now - %d\n", conf.Concurrency)
  366. }
  367. if conf.MaxClients <= 0 {
  368. conf.MaxClients = conf.Concurrency * 10
  369. }
  370. if conf.TTL <= 0 {
  371. return fmt.Errorf("TTL should be greater than 0, now - %d\n", conf.TTL)
  372. }
  373. if conf.MaxSrcDimension < 0 {
  374. return fmt.Errorf("Max src dimension should be greater than or equal to 0, now - %d\n", conf.MaxSrcDimension)
  375. } else if conf.MaxSrcDimension > 0 {
  376. logWarning("IMGPROXY_MAX_SRC_DIMENSION is deprecated and can be removed in future versions. Use IMGPROXY_MAX_SRC_RESOLUTION")
  377. }
  378. if conf.MaxSrcResolution <= 0 {
  379. return fmt.Errorf("Max src resolution should be greater than 0, now - %d\n", conf.MaxSrcResolution)
  380. }
  381. if conf.MaxSrcFileSize < 0 {
  382. return fmt.Errorf("Max src file size should be greater than or equal to 0, now - %d\n", conf.MaxSrcFileSize)
  383. }
  384. if conf.MaxAnimationFrames <= 0 {
  385. return fmt.Errorf("Max animation frames should be greater than 0, now - %d\n", conf.MaxAnimationFrames)
  386. }
  387. if conf.PngQuantizationColors < 2 {
  388. return fmt.Errorf("Png quantization colors should be greater than 1, now - %d\n", conf.PngQuantizationColors)
  389. } else if conf.PngQuantizationColors > 256 {
  390. return fmt.Errorf("Png quantization colors can't be greater than 256, now - %d\n", conf.PngQuantizationColors)
  391. }
  392. if conf.Quality <= 0 {
  393. return fmt.Errorf("Quality should be greater than 0, now - %d\n", conf.Quality)
  394. } else if conf.Quality > 100 {
  395. return fmt.Errorf("Quality can't be greater than 100, now - %d\n", conf.Quality)
  396. }
  397. if conf.GZipCompression < 0 {
  398. return fmt.Errorf("GZip compression should be greater than or equal to 0, now - %d\n", conf.GZipCompression)
  399. } else if conf.GZipCompression > 9 {
  400. return fmt.Errorf("GZip compression can't be greater than 9, now - %d\n", conf.GZipCompression)
  401. }
  402. if conf.GZipCompression > 0 {
  403. logWarning("GZip compression is deprecated and can be removed in future versions")
  404. }
  405. if conf.IgnoreSslVerification {
  406. logWarning("Ignoring SSL verification is very unsafe")
  407. }
  408. if conf.LocalFileSystemRoot != "" {
  409. stat, err := os.Stat(conf.LocalFileSystemRoot)
  410. if err != nil {
  411. return fmt.Errorf("Cannot use local directory: %s", err)
  412. }
  413. if !stat.IsDir() {
  414. return fmt.Errorf("Cannot use local directory: not a directory")
  415. }
  416. if conf.LocalFileSystemRoot == "/" {
  417. logWarning("Exposing root via IMGPROXY_LOCAL_FILESYSTEM_ROOT is unsafe")
  418. }
  419. }
  420. if _, ok := os.LookupEnv("IMGPROXY_USE_GCS"); !ok && len(conf.GCSKey) > 0 {
  421. logWarning("Set IMGPROXY_USE_GCS to true since it may be required by future versions to enable GCS support")
  422. conf.GCSEnabled = true
  423. }
  424. if conf.WatermarkOpacity <= 0 {
  425. return fmt.Errorf("Watermark opacity should be greater than 0")
  426. } else if conf.WatermarkOpacity > 1 {
  427. return fmt.Errorf("Watermark opacity should be less than or equal to 1")
  428. }
  429. if len(conf.PrometheusBind) > 0 && conf.PrometheusBind == conf.Bind {
  430. return fmt.Errorf("Can't use the same binding for the main server and Prometheus")
  431. }
  432. if conf.FreeMemoryInterval <= 0 {
  433. return fmt.Errorf("Free memory interval should be greater than zero")
  434. }
  435. if conf.DownloadBufferSize < 0 {
  436. return fmt.Errorf("Download buffer size should be greater than or equal to 0")
  437. } else if conf.DownloadBufferSize > math.MaxInt32 {
  438. return fmt.Errorf("Download buffer size can't be greater than %d", math.MaxInt32)
  439. }
  440. if conf.GZipBufferSize < 0 {
  441. return fmt.Errorf("GZip buffer size should be greater than or equal to 0")
  442. } else if conf.GZipBufferSize > math.MaxInt32 {
  443. return fmt.Errorf("GZip buffer size can't be greater than %d", math.MaxInt32)
  444. }
  445. if conf.BufferPoolCalibrationThreshold < 64 {
  446. return fmt.Errorf("Buffer pool calibration threshold should be greater than or equal to 64")
  447. }
  448. return nil
  449. }