diff --git a/CHANGELOG.md b/CHANGELOG.md index ad435572..2f830287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - `imgproxy health` command. - (pro) `IMGPROXY_GIF_OPTIMIZE_FRAMES` & `IMGPROXY_GIF_OPTIMIZE_TRANSPARENCY` configs and `gif_options` processing option. +### Changed + +- Better SVG detection. + ### Fixed - Fix detection of SVG starting with a comment. diff --git a/config.go b/config.go index 76901ac7..a6249879 100644 --- a/config.go +++ b/config.go @@ -163,6 +163,7 @@ type config struct { MaxSrcResolution int MaxSrcFileSize int MaxAnimationFrames int + MaxSvgCheckBytes int JpegProgressive bool PngInterlaced bool @@ -245,6 +246,7 @@ var conf = config{ TTL: 3600, MaxSrcResolution: 16800000, MaxAnimationFrames: 1, + MaxSvgCheckBytes: 32 * 1024, SignatureSize: 32, PngQuantizationColors: 256, Quality: 80, @@ -294,6 +296,7 @@ func configure() { intEnvConfig(&conf.MaxSrcDimension, "IMGPROXY_MAX_SRC_DIMENSION") megaIntEnvConfig(&conf.MaxSrcResolution, "IMGPROXY_MAX_SRC_RESOLUTION") intEnvConfig(&conf.MaxSrcFileSize, "IMGPROXY_MAX_SRC_FILE_SIZE") + intEnvConfig(&conf.MaxSvgCheckBytes, "IMGPROXY_MAX_SVG_CHECK_BYTES") 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") diff --git a/docs/configuration.md b/docs/configuration.md index 1f326a6b..2e4132b0 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -53,6 +53,10 @@ imgproxy can process animated images (GIF, WebP), but since this operation is pr **Note:** imgproxy summarizes all frames resolutions while checking source image resolution. +imgproxy reads some amount of bytes to check if the source image is SVG. By default it reads maximum of 32KB, but you can change this: + +* `IMGPROXY_MAX_SVG_CHECK_BYTES`: the maximum number of bytes imgproxy will read to recognize SVG. If imgproxy can't recognize your SVG, try to increase this number. Default: `32768` (32KB) + You can also specify a secret to enable authorization with the HTTP `Authorization` header for use in production environments: * `IMGPROXY_SECRET`: the authorization token. If specified, the HTTP request should contain the `Authorization: Bearer %secret%` header; diff --git a/docs/image_formats_support.md b/docs/image_formats_support.md index 353918be..e0bc4b6b 100644 --- a/docs/image_formats_support.md +++ b/docs/image_formats_support.md @@ -27,6 +27,10 @@ imgproxy supports SVG sources without limitations, but SVG results are not suppo When the source image is SVG and the SVG result is requested, imgproxy returns source image without modifications. +imgproxy reads some amount of bytes to check if the source image is SVG. By default it reads maximum of 32KB, but you can change this: + +* `IMGPROXY_MAX_SVG_CHECK_BYTES`: the maximum number of bytes imgproxy will read to recognize SVG. If imgproxy can't recognize your SVG, try to increase this number. Default: `32768` (32KB) + ## HEIC support imgproxy supports HEIC only when using libvips 8.8.0+. Official imgproxy Docker image supports HEIC out of the box. diff --git a/download.go b/download.go index 8bb98c03..a15bd3d3 100644 --- a/download.go +++ b/download.go @@ -90,6 +90,8 @@ func initDownloading() { } downloadBufPool = newBufPool("download", conf.Concurrency, conf.DownloadBufferSize) + + imagemeta.SetMaxSvgCheckRead(conf.MaxSvgCheckBytes) } func checkDimensions(width, height int) error { diff --git a/imagemeta/image_meta.go b/imagemeta/image_meta.go index 575f45ad..ffa9612f 100644 --- a/imagemeta/image_meta.go +++ b/imagemeta/image_meta.go @@ -88,5 +88,11 @@ func DecodeMeta(r io.Reader) (Meta, error) { } } + if ok, err := IsSVG(rr); err != nil { + return nil, err + } else if ok { + return &meta{format: "svg", width: 1, height: 1}, nil + } + return nil, ErrFormat } diff --git a/imagemeta/svg.go b/imagemeta/svg.go index a4096f3d..442c588b 100644 --- a/imagemeta/svg.go +++ b/imagemeta/svg.go @@ -1,17 +1,48 @@ package imagemeta import ( + "encoding/xml" "io" + "sync/atomic" ) -func init() { - // Register fake svg decoder. Since we need this only for type detecting, we can - // return fake image sizes - decodeMeta := func(io.Reader) (Meta, error) { - return &meta{format: "svg", width: 1, height: 1}, nil - } - RegisterFormat("= maxBytes { + break + } + } + + return false, nil }