2017-06-20 15:58:55 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-09-07 19:41:06 +02:00
|
|
|
"bufio"
|
2017-06-20 15:58:55 +02:00
|
|
|
"encoding/hex"
|
|
|
|
"flag"
|
2017-09-30 02:10:41 +02:00
|
|
|
"fmt"
|
2019-08-13 13:25:54 +02:00
|
|
|
"math"
|
2017-06-20 15:58:55 +02:00
|
|
|
"os"
|
2017-09-28 19:17:23 +02:00
|
|
|
"runtime"
|
2017-06-26 00:20:48 +02:00
|
|
|
"strconv"
|
2018-09-07 19:41:06 +02:00
|
|
|
"strings"
|
2017-06-20 15:58:55 +02:00
|
|
|
)
|
|
|
|
|
2017-06-26 00:20:48 +02:00
|
|
|
func intEnvConfig(i *int, name string) {
|
|
|
|
if env, err := strconv.Atoi(os.Getenv(name)); err == nil {
|
|
|
|
*i = env
|
|
|
|
}
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|
|
|
|
|
2018-10-19 11:47:11 +02:00
|
|
|
func floatEnvConfig(i *float64, name string) {
|
|
|
|
if env, err := strconv.ParseFloat(os.Getenv(name), 64); err == nil {
|
|
|
|
*i = env
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-07 01:00:31 +02:00
|
|
|
func megaIntEnvConfig(f *int, name string) {
|
|
|
|
if env, err := strconv.ParseFloat(os.Getenv(name), 64); err == nil {
|
|
|
|
*f = int(env * 1000000)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-26 00:20:48 +02:00
|
|
|
func strEnvConfig(s *string, name string) {
|
|
|
|
if env := os.Getenv(name); len(env) > 0 {
|
|
|
|
*s = env
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2019-12-25 13:30:23 +02:00
|
|
|
func strSliceEnvConfig(s *[]string, name string) {
|
|
|
|
if env := os.Getenv(name); len(env) > 0 {
|
|
|
|
parts := strings.Split(env, ",")
|
|
|
|
|
|
|
|
for i, p := range parts {
|
|
|
|
parts[i] = strings.TrimSpace(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
*s = parts
|
2020-01-13 16:00:50 +02:00
|
|
|
|
|
|
|
return
|
2019-12-25 13:30:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*s = []string{}
|
|
|
|
}
|
|
|
|
|
2018-02-26 10:45:52 +02:00
|
|
|
func boolEnvConfig(b *bool, name string) {
|
|
|
|
if env, err := strconv.ParseBool(os.Getenv(name)); err == nil {
|
|
|
|
*b = env
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-13 15:52:35 +02:00
|
|
|
func imageTypesEnvConfig(it *[]imageType, name string) {
|
|
|
|
*it = []imageType{}
|
|
|
|
|
|
|
|
if env := os.Getenv(name); len(env) > 0 {
|
|
|
|
parts := strings.Split(env, ",")
|
|
|
|
|
|
|
|
for _, p := range parts {
|
|
|
|
pt := strings.TrimSpace(p)
|
|
|
|
if t, ok := imageTypes[pt]; ok {
|
|
|
|
*it = append(*it, t)
|
|
|
|
} else {
|
|
|
|
logWarning("Unknown image format to skip: %s", pt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
func hexEnvConfig(b *[]securityKey, name string) error {
|
2017-06-26 00:20:48 +02:00
|
|
|
var err error
|
|
|
|
|
|
|
|
if env := os.Getenv(name); len(env) > 0 {
|
2018-11-15 14:35:06 +02:00
|
|
|
parts := strings.Split(env, ",")
|
|
|
|
|
|
|
|
keys := make([]securityKey, len(parts))
|
|
|
|
|
|
|
|
for i, part := range parts {
|
|
|
|
if keys[i], err = hex.DecodeString(part); err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("%s expected to be hex-encoded strings. Invalid: %s\n", name, part)
|
2018-11-15 14:35:06 +02:00
|
|
|
}
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2018-11-15 14:35:06 +02:00
|
|
|
|
|
|
|
*b = keys
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2020-02-27 17:44:59 +02:00
|
|
|
|
|
|
|
return nil
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
func hexFileConfig(b *[]securityKey, filepath string) error {
|
2017-06-26 00:20:48 +02:00
|
|
|
if len(filepath) == 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return nil
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2017-06-27 10:29:57 +02:00
|
|
|
f, err := os.Open(filepath)
|
2017-06-20 15:58:55 +02:00
|
|
|
if err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Can't open file %s\n", filepath)
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|
|
|
|
|
2018-11-15 14:35:06 +02:00
|
|
|
keys := []securityKey{}
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2018-11-15 14:35:06 +02:00
|
|
|
scanner := bufio.NewScanner(f)
|
|
|
|
for scanner.Scan() {
|
|
|
|
part := scanner.Text()
|
2017-06-26 00:20:48 +02:00
|
|
|
|
2018-11-15 14:35:06 +02:00
|
|
|
if len(part) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if key, err := hex.DecodeString(part); err == nil {
|
|
|
|
keys = append(keys, key)
|
|
|
|
} else {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("%s expected to contain hex-encoded strings. Invalid: %s\n", filepath, part)
|
2018-11-15 14:35:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := scanner.Err(); err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Failed to read file %s: %s", filepath, err)
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|
|
|
|
|
2018-11-15 14:35:06 +02:00
|
|
|
*b = keys
|
2020-02-27 17:44:59 +02:00
|
|
|
|
|
|
|
return nil
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
func presetEnvConfig(p presets, name string) error {
|
2018-09-07 19:41:06 +02:00
|
|
|
if env := os.Getenv(name); len(env) > 0 {
|
|
|
|
presetStrings := strings.Split(env, ",")
|
|
|
|
|
|
|
|
for _, presetStr := range presetStrings {
|
2018-11-06 13:19:34 +02:00
|
|
|
if err := parsePreset(p, presetStr); err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf(err.Error())
|
2018-11-06 13:19:34 +02:00
|
|
|
}
|
2018-09-07 19:41:06 +02:00
|
|
|
}
|
|
|
|
}
|
2020-02-27 17:44:59 +02:00
|
|
|
|
|
|
|
return nil
|
2018-09-07 19:41:06 +02:00
|
|
|
}
|
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
func presetFileConfig(p presets, filepath string) error {
|
2018-09-07 19:41:06 +02:00
|
|
|
if len(filepath) == 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return nil
|
2018-09-07 19:41:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
f, err := os.Open(filepath)
|
|
|
|
if err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Can't open file %s\n", filepath)
|
2018-09-07 19:41:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
|
|
for scanner.Scan() {
|
2018-11-06 13:19:34 +02:00
|
|
|
if err := parsePreset(p, scanner.Text()); err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf(err.Error())
|
2018-11-06 13:19:34 +02:00
|
|
|
}
|
2018-09-07 19:41:06 +02:00
|
|
|
}
|
2018-09-12 15:46:43 +02:00
|
|
|
|
|
|
|
if err := scanner.Err(); err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Failed to read presets file: %s", err)
|
2018-09-12 15:46:43 +02:00
|
|
|
}
|
2020-02-27 17:44:59 +02:00
|
|
|
|
|
|
|
return nil
|
2018-09-07 19:41:06 +02:00
|
|
|
}
|
|
|
|
|
2017-06-26 00:20:48 +02:00
|
|
|
type config struct {
|
2020-02-03 14:03:18 +02:00
|
|
|
Network string
|
2019-06-21 12:32:37 +02:00
|
|
|
Bind string
|
|
|
|
ReadTimeout int
|
|
|
|
WriteTimeout int
|
|
|
|
KeepAliveTimeout int
|
|
|
|
DownloadTimeout int
|
|
|
|
Concurrency int
|
|
|
|
MaxClients int
|
2020-02-04 11:23:41 +02:00
|
|
|
|
|
|
|
TTL int
|
|
|
|
CacheControlPassthrough bool
|
|
|
|
|
|
|
|
SoReuseport bool
|
2017-07-03 12:10:44 +02:00
|
|
|
|
2020-04-07 13:54:00 +02:00
|
|
|
PathPrefix string
|
|
|
|
|
2019-06-11 17:42:21 +02:00
|
|
|
MaxSrcDimension int
|
|
|
|
MaxSrcResolution int
|
|
|
|
MaxSrcFileSize int
|
|
|
|
MaxAnimationFrames int
|
2020-02-11 15:28:13 +02:00
|
|
|
MaxSvgCheckBytes int
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2019-04-05 12:30:16 +02:00
|
|
|
JpegProgressive bool
|
|
|
|
PngInterlaced bool
|
|
|
|
PngQuantize bool
|
|
|
|
PngQuantizationColors int
|
|
|
|
Quality int
|
|
|
|
GZipCompression int
|
2020-01-30 17:43:08 +02:00
|
|
|
StripMetadata bool
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2018-09-11 14:26:27 +02:00
|
|
|
EnableWebpDetection bool
|
|
|
|
EnforceWebp bool
|
2018-11-02 18:38:41 +02:00
|
|
|
EnableClientHints bool
|
2018-09-11 14:26:27 +02:00
|
|
|
|
2020-08-13 15:52:35 +02:00
|
|
|
SkipProcessingFormats []imageType
|
|
|
|
|
2019-04-04 17:57:44 +02:00
|
|
|
UseLinearColorspace bool
|
2019-04-01 17:30:53 +02:00
|
|
|
DisableShrinkOnLoad bool
|
|
|
|
|
2018-11-15 14:35:06 +02:00
|
|
|
Keys []securityKey
|
|
|
|
Salts []securityKey
|
2018-09-12 21:14:43 +02:00
|
|
|
AllowInsecure bool
|
2018-11-02 13:10:20 +02:00
|
|
|
SignatureSize int
|
2017-07-01 23:25:08 +02:00
|
|
|
|
|
|
|
Secret string
|
2017-12-29 21:59:20 +02:00
|
|
|
|
2018-04-26 13:22:31 +02:00
|
|
|
AllowOrigin string
|
|
|
|
|
2018-10-30 15:37:41 +02:00
|
|
|
UserAgent string
|
|
|
|
|
2018-09-26 15:00:37 +02:00
|
|
|
IgnoreSslVerification bool
|
2019-05-08 16:51:39 +02:00
|
|
|
DevelopmentErrorsMode bool
|
2018-09-26 15:00:37 +02:00
|
|
|
|
2019-12-25 10:34:15 +02:00
|
|
|
AllowedSources []string
|
2017-12-29 21:59:20 +02:00
|
|
|
LocalFileSystemRoot string
|
2018-10-04 17:12:51 +02:00
|
|
|
S3Enabled bool
|
2018-11-13 15:23:59 +02:00
|
|
|
S3Region string
|
|
|
|
S3Endpoint string
|
2019-09-30 15:10:55 +02:00
|
|
|
GCSEnabled bool
|
2018-10-30 14:12:56 +02:00
|
|
|
GCSKey string
|
2018-02-26 11:41:37 +02:00
|
|
|
|
2018-09-06 15:02:21 +02:00
|
|
|
ETagEnabled bool
|
2018-04-26 13:38:40 +02:00
|
|
|
|
|
|
|
BaseURL string
|
2018-09-07 19:41:06 +02:00
|
|
|
|
2019-05-16 12:24:42 +02:00
|
|
|
Presets presets
|
|
|
|
OnlyPresets bool
|
2018-10-19 11:47:11 +02:00
|
|
|
|
|
|
|
WatermarkData string
|
|
|
|
WatermarkPath string
|
|
|
|
WatermarkURL string
|
|
|
|
WatermarkOpacity float64
|
2018-10-25 15:24:34 +02:00
|
|
|
|
2020-04-08 16:32:45 +02:00
|
|
|
FallbackImageData string
|
|
|
|
FallbackImagePath string
|
|
|
|
FallbackImageURL string
|
|
|
|
|
2018-10-25 15:24:34 +02:00
|
|
|
NewRelicAppName string
|
|
|
|
NewRelicKey string
|
2018-10-29 14:04:47 +02:00
|
|
|
|
2020-06-10 15:11:14 +02:00
|
|
|
PrometheusBind string
|
|
|
|
PrometheusNamespace string
|
2018-11-14 15:41:16 +02:00
|
|
|
|
2019-01-14 12:42:10 +02:00
|
|
|
BugsnagKey string
|
|
|
|
BugsnagStage string
|
|
|
|
HoneybadgerKey string
|
|
|
|
HoneybadgerEnv string
|
|
|
|
SentryDSN string
|
|
|
|
SentryEnvironment string
|
|
|
|
SentryRelease string
|
2019-01-17 10:51:19 +02:00
|
|
|
|
2019-10-01 11:18:37 +02:00
|
|
|
ReportDownloadingErrors bool
|
|
|
|
|
2019-02-01 13:13:00 +02:00
|
|
|
FreeMemoryInterval int
|
|
|
|
DownloadBufferSize int
|
2019-05-08 13:42:48 +02:00
|
|
|
GZipBufferSize int
|
2019-02-01 13:13:00 +02:00
|
|
|
BufferPoolCalibrationThreshold int
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2017-06-26 00:20:48 +02:00
|
|
|
var conf = config{
|
2020-02-03 14:03:18 +02:00
|
|
|
Network: "tcp",
|
2019-02-01 13:13:00 +02:00
|
|
|
Bind: ":8080",
|
|
|
|
ReadTimeout: 10,
|
|
|
|
WriteTimeout: 10,
|
2019-06-21 12:32:37 +02:00
|
|
|
KeepAliveTimeout: 10,
|
2019-02-01 13:13:00 +02:00
|
|
|
DownloadTimeout: 5,
|
|
|
|
Concurrency: runtime.NumCPU() * 2,
|
|
|
|
TTL: 3600,
|
|
|
|
MaxSrcResolution: 16800000,
|
2019-06-11 17:42:21 +02:00
|
|
|
MaxAnimationFrames: 1,
|
2020-02-11 15:28:13 +02:00
|
|
|
MaxSvgCheckBytes: 32 * 1024,
|
2019-02-01 13:13:00 +02:00
|
|
|
SignatureSize: 32,
|
2019-04-05 12:30:16 +02:00
|
|
|
PngQuantizationColors: 256,
|
2019-02-01 13:13:00 +02:00
|
|
|
Quality: 80,
|
2020-01-30 17:43:08 +02:00
|
|
|
StripMetadata: true,
|
2019-02-01 13:13:00 +02:00
|
|
|
UserAgent: fmt.Sprintf("imgproxy/%s", version),
|
2019-05-16 13:44:38 +02:00
|
|
|
Presets: make(presets),
|
2019-02-01 13:13:00 +02:00
|
|
|
WatermarkOpacity: 1,
|
|
|
|
BugsnagStage: "production",
|
|
|
|
HoneybadgerEnv: "production",
|
|
|
|
SentryEnvironment: "production",
|
|
|
|
SentryRelease: fmt.Sprintf("imgproxy/%s", version),
|
2019-10-01 11:18:37 +02:00
|
|
|
ReportDownloadingErrors: true,
|
2019-02-01 13:13:00 +02:00
|
|
|
FreeMemoryInterval: 10,
|
|
|
|
BufferPoolCalibrationThreshold: 1024,
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
func configure() error {
|
2018-09-07 19:41:06 +02:00
|
|
|
keyPath := flag.String("keypath", "", "path of the file with hex-encoded key")
|
|
|
|
saltPath := flag.String("saltpath", "", "path of the file with hex-encoded salt")
|
|
|
|
presetsPath := flag.String("presets", "", "path of the file with presets")
|
2017-06-26 00:20:48 +02:00
|
|
|
flag.Parse()
|
|
|
|
|
2017-09-30 02:10:41 +02:00
|
|
|
if port := os.Getenv("PORT"); len(port) > 0 {
|
|
|
|
conf.Bind = fmt.Sprintf(":%s", port)
|
|
|
|
}
|
|
|
|
|
2020-02-03 14:03:18 +02:00
|
|
|
strEnvConfig(&conf.Network, "IMGPROXY_NETWORK")
|
2017-06-26 00:20:48 +02:00
|
|
|
strEnvConfig(&conf.Bind, "IMGPROXY_BIND")
|
|
|
|
intEnvConfig(&conf.ReadTimeout, "IMGPROXY_READ_TIMEOUT")
|
|
|
|
intEnvConfig(&conf.WriteTimeout, "IMGPROXY_WRITE_TIMEOUT")
|
2019-06-21 12:32:37 +02:00
|
|
|
intEnvConfig(&conf.KeepAliveTimeout, "IMGPROXY_KEEP_ALIVE_TIMEOUT")
|
2017-07-05 14:28:22 +02:00
|
|
|
intEnvConfig(&conf.DownloadTimeout, "IMGPROXY_DOWNLOAD_TIMEOUT")
|
2017-07-04 16:05:53 +02:00
|
|
|
intEnvConfig(&conf.Concurrency, "IMGPROXY_CONCURRENCY")
|
2017-09-15 12:29:51 +02:00
|
|
|
intEnvConfig(&conf.MaxClients, "IMGPROXY_MAX_CLIENTS")
|
2017-06-26 00:20:48 +02:00
|
|
|
|
2017-07-03 12:10:44 +02:00
|
|
|
intEnvConfig(&conf.TTL, "IMGPROXY_TTL")
|
2020-02-04 11:23:41 +02:00
|
|
|
boolEnvConfig(&conf.CacheControlPassthrough, "IMGPROXY_CACHE_CONTROL_PASSTHROUGH")
|
2017-07-03 12:10:44 +02:00
|
|
|
|
2019-06-27 10:00:39 +02:00
|
|
|
boolEnvConfig(&conf.SoReuseport, "IMGPROXY_SO_REUSEPORT")
|
|
|
|
|
2020-04-07 13:54:00 +02:00
|
|
|
strEnvConfig(&conf.PathPrefix, "IMGPROXY_PATH_PREFIX")
|
|
|
|
|
2017-06-26 00:20:48 +02:00
|
|
|
intEnvConfig(&conf.MaxSrcDimension, "IMGPROXY_MAX_SRC_DIMENSION")
|
2017-10-07 01:00:31 +02:00
|
|
|
megaIntEnvConfig(&conf.MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION")
|
2019-01-21 12:36:31 +02:00
|
|
|
intEnvConfig(&conf.MaxSrcFileSize, "IMGPROXY_MAX_SRC_FILE_SIZE")
|
2020-02-11 15:28:13 +02:00
|
|
|
intEnvConfig(&conf.MaxSvgCheckBytes, "IMGPROXY_MAX_SVG_CHECK_BYTES")
|
2019-06-11 17:42:21 +02:00
|
|
|
|
|
|
|
if _, ok := os.LookupEnv("IMGPROXY_MAX_GIF_FRAMES"); ok {
|
|
|
|
logWarning("`IMGPROXY_MAX_GIF_FRAMES` is deprecated and will be removed in future versions. Use `IMGPROXY_MAX_ANIMATION_FRAMES` instead")
|
|
|
|
intEnvConfig(&conf.MaxAnimationFrames, "IMGPROXY_MAX_GIF_FRAMES")
|
|
|
|
}
|
|
|
|
intEnvConfig(&conf.MaxAnimationFrames, "IMGPROXY_MAX_ANIMATION_FRAMES")
|
2017-06-26 00:20:48 +02:00
|
|
|
|
2019-12-25 13:30:23 +02:00
|
|
|
strSliceEnvConfig(&conf.AllowedSources, "IMGPROXY_ALLOWED_SOURCES")
|
2019-12-25 10:49:20 +02:00
|
|
|
|
2018-07-16 17:14:24 +02:00
|
|
|
boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE")
|
|
|
|
boolEnvConfig(&conf.PngInterlaced, "IMGPROXY_PNG_INTERLACED")
|
2019-04-05 12:30:16 +02:00
|
|
|
boolEnvConfig(&conf.PngQuantize, "IMGPROXY_PNG_QUANTIZE")
|
|
|
|
intEnvConfig(&conf.PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS")
|
2017-06-26 00:20:48 +02:00
|
|
|
intEnvConfig(&conf.Quality, "IMGPROXY_QUALITY")
|
2017-06-27 02:41:37 +02:00
|
|
|
intEnvConfig(&conf.GZipCompression, "IMGPROXY_GZIP_COMPRESSION")
|
2020-01-30 17:43:08 +02:00
|
|
|
boolEnvConfig(&conf.StripMetadata, "IMGPROXY_STRIP_METADATA")
|
2017-06-20 15:58:55 +02:00
|
|
|
|
2018-09-11 14:26:27 +02:00
|
|
|
boolEnvConfig(&conf.EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION")
|
|
|
|
boolEnvConfig(&conf.EnforceWebp, "IMGPROXY_ENFORCE_WEBP")
|
2018-11-02 18:38:41 +02:00
|
|
|
boolEnvConfig(&conf.EnableClientHints, "IMGPROXY_ENABLE_CLIENT_HINTS")
|
2018-09-11 14:26:27 +02:00
|
|
|
|
2020-08-13 15:52:35 +02:00
|
|
|
imageTypesEnvConfig(&conf.SkipProcessingFormats, "IMGPROXY_SKIP_PROCESSING_FORMATS")
|
|
|
|
|
2019-04-04 17:57:44 +02:00
|
|
|
boolEnvConfig(&conf.UseLinearColorspace, "IMGPROXY_USE_LINEAR_COLORSPACE")
|
2019-04-01 17:30:53 +02:00
|
|
|
boolEnvConfig(&conf.DisableShrinkOnLoad, "IMGPROXY_DISABLE_SHRINK_ON_LOAD")
|
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
if err := hexEnvConfig(&conf.Keys, "IMGPROXY_KEY"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := hexEnvConfig(&conf.Salts, "IMGPROXY_SALT"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-11-02 13:10:20 +02:00
|
|
|
intEnvConfig(&conf.SignatureSize, "IMGPROXY_SIGNATURE_SIZE")
|
2017-06-26 00:20:48 +02:00
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
if err := hexFileConfig(&conf.Keys, *keyPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := hexFileConfig(&conf.Salts, *saltPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-06-26 00:20:48 +02:00
|
|
|
|
2017-07-01 23:25:08 +02:00
|
|
|
strEnvConfig(&conf.Secret, "IMGPROXY_SECRET")
|
|
|
|
|
2018-04-26 13:22:31 +02:00
|
|
|
strEnvConfig(&conf.AllowOrigin, "IMGPROXY_ALLOW_ORIGIN")
|
|
|
|
|
2018-10-30 15:37:41 +02:00
|
|
|
strEnvConfig(&conf.UserAgent, "IMGPROXY_USER_AGENT")
|
|
|
|
|
2018-09-26 15:00:37 +02:00
|
|
|
boolEnvConfig(&conf.IgnoreSslVerification, "IMGPROXY_IGNORE_SSL_VERIFICATION")
|
2019-05-08 16:51:39 +02:00
|
|
|
boolEnvConfig(&conf.DevelopmentErrorsMode, "IMGPROXY_DEVELOPMENT_ERRORS_MODE")
|
2018-09-26 15:00:37 +02:00
|
|
|
|
2017-12-29 21:59:20 +02:00
|
|
|
strEnvConfig(&conf.LocalFileSystemRoot, "IMGPROXY_LOCAL_FILESYSTEM_ROOT")
|
2018-02-26 11:41:37 +02:00
|
|
|
|
2018-05-26 16:22:41 +02:00
|
|
|
boolEnvConfig(&conf.S3Enabled, "IMGPROXY_USE_S3")
|
2018-11-13 15:23:59 +02:00
|
|
|
strEnvConfig(&conf.S3Region, "IMGPROXY_S3_REGION")
|
|
|
|
strEnvConfig(&conf.S3Endpoint, "IMGPROXY_S3_ENDPOINT")
|
|
|
|
|
2019-09-30 15:10:55 +02:00
|
|
|
boolEnvConfig(&conf.GCSEnabled, "IMGPROXY_USE_GCS")
|
2018-10-30 14:12:56 +02:00
|
|
|
strEnvConfig(&conf.GCSKey, "IMGPROXY_GCS_KEY")
|
2018-05-26 16:22:41 +02:00
|
|
|
|
2018-02-26 10:45:52 +02:00
|
|
|
boolEnvConfig(&conf.ETagEnabled, "IMGPROXY_USE_ETAG")
|
2017-12-29 21:59:20 +02:00
|
|
|
|
2018-04-26 13:38:40 +02:00
|
|
|
strEnvConfig(&conf.BaseURL, "IMGPROXY_BASE_URL")
|
|
|
|
|
2020-02-27 17:44:59 +02:00
|
|
|
if err := presetEnvConfig(conf.Presets, "IMGPROXY_PRESETS"); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := presetFileConfig(conf.Presets, *presetsPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-05-16 12:24:42 +02:00
|
|
|
boolEnvConfig(&conf.OnlyPresets, "IMGPROXY_ONLY_PRESETS")
|
2018-09-07 19:41:06 +02:00
|
|
|
|
2018-10-19 11:47:11 +02:00
|
|
|
strEnvConfig(&conf.WatermarkData, "IMGPROXY_WATERMARK_DATA")
|
|
|
|
strEnvConfig(&conf.WatermarkPath, "IMGPROXY_WATERMARK_PATH")
|
|
|
|
strEnvConfig(&conf.WatermarkURL, "IMGPROXY_WATERMARK_URL")
|
|
|
|
floatEnvConfig(&conf.WatermarkOpacity, "IMGPROXY_WATERMARK_OPACITY")
|
|
|
|
|
2020-04-08 16:32:45 +02:00
|
|
|
strEnvConfig(&conf.FallbackImageData, "IMGPROXY_FALLBACK_IMAGE_DATA")
|
|
|
|
strEnvConfig(&conf.FallbackImagePath, "IMGPROXY_FALLBACK_IMAGE_PATH")
|
|
|
|
strEnvConfig(&conf.FallbackImageURL, "IMGPROXY_FALLBACK_IMAGE_URL")
|
|
|
|
|
2018-10-25 15:24:34 +02:00
|
|
|
strEnvConfig(&conf.NewRelicAppName, "IMGPROXY_NEW_RELIC_APP_NAME")
|
|
|
|
strEnvConfig(&conf.NewRelicKey, "IMGPROXY_NEW_RELIC_KEY")
|
|
|
|
|
2018-10-29 14:04:47 +02:00
|
|
|
strEnvConfig(&conf.PrometheusBind, "IMGPROXY_PROMETHEUS_BIND")
|
2020-06-10 15:11:14 +02:00
|
|
|
strEnvConfig(&conf.PrometheusNamespace, "IMGPROXY_PROMETHEUS_NAMESPACE")
|
2018-10-29 14:04:47 +02:00
|
|
|
|
2018-11-14 15:41:16 +02:00
|
|
|
strEnvConfig(&conf.BugsnagKey, "IMGPROXY_BUGSNAG_KEY")
|
|
|
|
strEnvConfig(&conf.BugsnagStage, "IMGPROXY_BUGSNAG_STAGE")
|
|
|
|
strEnvConfig(&conf.HoneybadgerKey, "IMGPROXY_HONEYBADGER_KEY")
|
|
|
|
strEnvConfig(&conf.HoneybadgerEnv, "IMGPROXY_HONEYBADGER_ENV")
|
2019-01-14 12:42:10 +02:00
|
|
|
strEnvConfig(&conf.SentryDSN, "IMGPROXY_SENTRY_DSN")
|
|
|
|
strEnvConfig(&conf.SentryEnvironment, "IMGPROXY_SENTRY_ENVIRONMENT")
|
|
|
|
strEnvConfig(&conf.SentryRelease, "IMGPROXY_SENTRY_RELEASE")
|
2019-10-01 11:18:37 +02:00
|
|
|
boolEnvConfig(&conf.ReportDownloadingErrors, "IMGPROXY_REPORT_DOWNLOADING_ERRORS")
|
2018-11-14 15:41:16 +02:00
|
|
|
|
2019-01-17 10:51:19 +02:00
|
|
|
intEnvConfig(&conf.FreeMemoryInterval, "IMGPROXY_FREE_MEMORY_INTERVAL")
|
|
|
|
intEnvConfig(&conf.DownloadBufferSize, "IMGPROXY_DOWNLOAD_BUFFER_SIZE")
|
2019-05-08 13:42:48 +02:00
|
|
|
intEnvConfig(&conf.GZipBufferSize, "IMGPROXY_GZIP_BUFFER_SIZE")
|
2019-02-01 13:13:00 +02:00
|
|
|
intEnvConfig(&conf.BufferPoolCalibrationThreshold, "IMGPROXY_BUFFER_POOL_CALIBRATION_THRESHOLD")
|
2019-01-17 10:51:19 +02:00
|
|
|
|
2018-11-15 14:35:06 +02:00
|
|
|
if len(conf.Keys) != len(conf.Salts) {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Number of keys and number of salts should be equal. Keys: %d, salts: %d", len(conf.Keys), len(conf.Salts))
|
2018-11-15 14:35:06 +02:00
|
|
|
}
|
|
|
|
if len(conf.Keys) == 0 {
|
2019-01-11 17:01:48 +02:00
|
|
|
logWarning("No keys defined, so signature checking is disabled")
|
2018-09-12 21:14:43 +02:00
|
|
|
conf.AllowInsecure = true
|
2017-06-26 00:20:48 +02:00
|
|
|
}
|
2018-11-15 14:35:06 +02:00
|
|
|
if len(conf.Salts) == 0 {
|
2019-01-11 17:01:48 +02:00
|
|
|
logWarning("No salts defined, so signature checking is disabled")
|
2018-09-12 21:14:43 +02:00
|
|
|
conf.AllowInsecure = true
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|
2018-11-15 14:35:06 +02:00
|
|
|
|
2018-11-02 13:10:20 +02:00
|
|
|
if conf.SignatureSize < 1 || conf.SignatureSize > 32 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Signature size should be within 1 and 32, now - %d\n", conf.SignatureSize)
|
2018-11-02 13:10:20 +02:00
|
|
|
}
|
2017-06-27 10:52:54 +02:00
|
|
|
|
|
|
|
if len(conf.Bind) == 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Bind address is not defined")
|
2017-06-27 10:52:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if conf.ReadTimeout <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Read timeout should be greater than 0, now - %d\n", conf.ReadTimeout)
|
2017-06-27 10:52:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if conf.WriteTimeout <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Write timeout should be greater than 0, now - %d\n", conf.WriteTimeout)
|
2017-06-27 10:52:54 +02:00
|
|
|
}
|
2019-06-21 12:32:37 +02:00
|
|
|
if conf.KeepAliveTimeout < 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("KeepAlive timeout should be greater than or equal to 0, now - %d\n", conf.KeepAliveTimeout)
|
2019-06-21 12:32:37 +02:00
|
|
|
}
|
2017-06-27 10:52:54 +02:00
|
|
|
|
2017-07-05 14:28:22 +02:00
|
|
|
if conf.DownloadTimeout <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Download timeout should be greater than 0, now - %d\n", conf.DownloadTimeout)
|
2017-07-05 14:28:22 +02:00
|
|
|
}
|
|
|
|
|
2017-07-04 16:05:53 +02:00
|
|
|
if conf.Concurrency <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Concurrency should be greater than 0, now - %d\n", conf.Concurrency)
|
2017-07-04 16:05:53 +02:00
|
|
|
}
|
|
|
|
|
2017-09-15 12:29:51 +02:00
|
|
|
if conf.MaxClients <= 0 {
|
2018-03-19 11:06:08 +02:00
|
|
|
conf.MaxClients = conf.Concurrency * 10
|
2017-09-15 12:29:51 +02:00
|
|
|
}
|
|
|
|
|
2017-07-03 12:10:44 +02:00
|
|
|
if conf.TTL <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("TTL should be greater than 0, now - %d\n", conf.TTL)
|
2017-07-03 12:10:44 +02:00
|
|
|
}
|
|
|
|
|
2018-11-15 15:25:53 +02:00
|
|
|
if conf.MaxSrcDimension < 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Max src dimension should be greater than or equal to 0, now - %d\n", conf.MaxSrcDimension)
|
2018-11-15 15:25:53 +02:00
|
|
|
} else if conf.MaxSrcDimension > 0 {
|
2019-01-11 17:01:48 +02:00
|
|
|
logWarning("IMGPROXY_MAX_SRC_DIMENSION is deprecated and can be removed in future versions. Use IMGPROXY_MAX_SRC_RESOLUTION")
|
2017-06-27 10:52:54 +02:00
|
|
|
}
|
|
|
|
|
2017-10-07 01:00:31 +02:00
|
|
|
if conf.MaxSrcResolution <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Max src resolution should be greater than 0, now - %d\n", conf.MaxSrcResolution)
|
2017-10-07 01:00:31 +02:00
|
|
|
}
|
|
|
|
|
2019-01-21 12:36:31 +02:00
|
|
|
if conf.MaxSrcFileSize < 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Max src file size should be greater than or equal to 0, now - %d\n", conf.MaxSrcFileSize)
|
2019-01-21 12:36:31 +02:00
|
|
|
}
|
|
|
|
|
2019-06-11 17:42:21 +02:00
|
|
|
if conf.MaxAnimationFrames <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Max animation frames should be greater than 0, now - %d\n", conf.MaxAnimationFrames)
|
2018-11-15 16:04:12 +02:00
|
|
|
}
|
|
|
|
|
2019-04-05 12:30:16 +02:00
|
|
|
if conf.PngQuantizationColors < 2 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Png quantization colors should be greater than 1, now - %d\n", conf.PngQuantizationColors)
|
2019-04-05 12:30:16 +02:00
|
|
|
} else if conf.PngQuantizationColors > 256 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Png quantization colors can't be greater than 256, now - %d\n", conf.PngQuantizationColors)
|
2019-04-05 12:30:16 +02:00
|
|
|
}
|
|
|
|
|
2017-06-27 10:52:54 +02:00
|
|
|
if conf.Quality <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Quality should be greater than 0, now - %d\n", conf.Quality)
|
2017-06-27 10:52:54 +02:00
|
|
|
} else if conf.Quality > 100 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Quality can't be greater than 100, now - %d\n", conf.Quality)
|
2017-06-27 10:52:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if conf.GZipCompression < 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("GZip compression should be greater than or equal to 0, now - %d\n", conf.GZipCompression)
|
2017-06-27 10:52:54 +02:00
|
|
|
} else if conf.GZipCompression > 9 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("GZip compression can't be greater than 9, now - %d\n", conf.GZipCompression)
|
2017-06-27 10:52:54 +02:00
|
|
|
}
|
2017-09-27 10:42:49 +02:00
|
|
|
|
2019-08-19 10:54:29 +02:00
|
|
|
if conf.GZipCompression > 0 {
|
|
|
|
logWarning("GZip compression is deprecated and can be removed in future versions")
|
|
|
|
}
|
|
|
|
|
2018-09-26 15:00:37 +02:00
|
|
|
if conf.IgnoreSslVerification {
|
2019-01-11 17:01:48 +02:00
|
|
|
logWarning("Ignoring SSL verification is very unsafe")
|
2018-09-26 15:00:37 +02:00
|
|
|
}
|
|
|
|
|
2017-12-29 21:59:20 +02:00
|
|
|
if conf.LocalFileSystemRoot != "" {
|
|
|
|
stat, err := os.Stat(conf.LocalFileSystemRoot)
|
2019-09-11 10:42:36 +02:00
|
|
|
|
2017-12-29 21:59:20 +02:00
|
|
|
if err != nil {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Cannot use local directory: %s", err)
|
2017-12-29 21:59:20 +02:00
|
|
|
}
|
2019-09-11 10:42:36 +02:00
|
|
|
|
|
|
|
if !stat.IsDir() {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Cannot use local directory: not a directory")
|
2019-09-11 10:42:36 +02:00
|
|
|
}
|
|
|
|
|
2017-12-29 21:59:20 +02:00
|
|
|
if conf.LocalFileSystemRoot == "/" {
|
2019-09-11 10:42:36 +02:00
|
|
|
logWarning("Exposing root via IMGPROXY_LOCAL_FILESYSTEM_ROOT is unsafe")
|
2017-12-29 21:59:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-30 15:10:55 +02:00
|
|
|
if _, ok := os.LookupEnv("IMGPROXY_USE_GCS"); !ok && len(conf.GCSKey) > 0 {
|
|
|
|
logWarning("Set IMGPROXY_USE_GCS to true since it may be required by future versions to enable GCS support")
|
|
|
|
conf.GCSEnabled = true
|
|
|
|
}
|
|
|
|
|
2018-10-19 11:47:11 +02:00
|
|
|
if conf.WatermarkOpacity <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Watermark opacity should be greater than 0")
|
2018-10-19 11:47:11 +02:00
|
|
|
} else if conf.WatermarkOpacity > 1 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Watermark opacity should be less than or equal to 1")
|
2018-10-19 11:47:11 +02:00
|
|
|
}
|
|
|
|
|
2018-10-29 14:04:47 +02:00
|
|
|
if len(conf.PrometheusBind) > 0 && conf.PrometheusBind == conf.Bind {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Can't use the same binding for the main server and Prometheus")
|
2018-10-29 14:04:47 +02:00
|
|
|
}
|
|
|
|
|
2019-01-17 10:51:19 +02:00
|
|
|
if conf.FreeMemoryInterval <= 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Free memory interval should be greater than zero")
|
2019-01-17 10:51:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if conf.DownloadBufferSize < 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Download buffer size should be greater than or equal to 0")
|
2019-08-13 13:25:54 +02:00
|
|
|
} else if conf.DownloadBufferSize > math.MaxInt32 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Download buffer size can't be greater than %d", math.MaxInt32)
|
2019-01-17 10:51:19 +02:00
|
|
|
}
|
|
|
|
|
2019-05-08 13:42:48 +02:00
|
|
|
if conf.GZipBufferSize < 0 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("GZip buffer size should be greater than or equal to 0")
|
2019-08-13 13:25:54 +02:00
|
|
|
} else if conf.GZipBufferSize > math.MaxInt32 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("GZip buffer size can't be greater than %d", math.MaxInt32)
|
2019-05-08 13:42:48 +02:00
|
|
|
}
|
|
|
|
|
2019-02-01 13:13:00 +02:00
|
|
|
if conf.BufferPoolCalibrationThreshold < 64 {
|
2020-02-27 17:44:59 +02:00
|
|
|
return fmt.Errorf("Buffer pool calibration threshold should be greater than or equal to 64")
|
2019-02-01 13:13:00 +02:00
|
|
|
}
|
2020-02-27 17:44:59 +02:00
|
|
|
|
|
|
|
return nil
|
2017-06-20 15:58:55 +02:00
|
|
|
}
|