diff --git a/config.go b/config.go
index 1c4e4db2..e46baec5 100644
--- a/config.go
+++ b/config.go
@@ -233,6 +233,8 @@ type config struct {
EnableWebpDetection bool
EnforceWebp bool
+ EnableAvifDetection bool
+ EnforceAvif bool
EnableClientHints bool
SkipProcessingFormats []imageType
@@ -389,6 +391,8 @@ func configure() error {
boolEnvConfig(&conf.EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION")
boolEnvConfig(&conf.EnforceWebp, "IMGPROXY_ENFORCE_WEBP")
+ boolEnvConfig(&conf.EnableAvifDetection, "IMGPROXY_ENABLE_AVIF_DETECTION")
+ boolEnvConfig(&conf.EnforceAvif, "IMGPROXY_ENFORCE_AVIF")
boolEnvConfig(&conf.EnableClientHints, "IMGPROXY_ENABLE_CLIENT_HINTS")
imageTypesEnvConfig(&conf.SkipProcessingFormats, "IMGPROXY_SKIP_PROCESSING_FORMATS")
diff --git a/docs/configuration.md b/docs/configuration.md
index 6ffa4a9f..ed32c340 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -121,14 +121,18 @@ Also you may want imgproxy to respond with the same error message that it writes
* `IMGPROXY_GIF_OPTIMIZE_FRAMES`: when true, enables GIF frames optimization. This may produce a smaller result, but may increase compression time.
* `IMGPROXY_GIF_OPTIMIZE_TRANSPARENCY`: when true, enables GIF transparency optimization. This may produce a smaller result, but may increase compression time.
-## WebP support detection
+## AVIF/WebP support detection
-imgproxy can use the `Accept` HTTP header to detect if the browser supports WebP and use it as the default format. This feature is disabled by default and can be enabled by the following options:
+imgproxy can use the `Accept` HTTP header to detect if the browser supports AVIF or WebP and use it as the default format. This feature is disabled by default and can be enabled by the following options:
* `IMGPROXY_ENABLE_WEBP_DETECTION`: enables WebP support detection. When the file extension is omitted in the imgproxy URL and browser supports WebP, imgproxy will use it as the resulting format;
* `IMGPROXY_ENFORCE_WEBP`: enables WebP support detection and enforces WebP usage. If the browser supports WebP, it will be used as resulting format even if another extension is specified in the imgproxy URL.
+* `IMGPROXY_ENABLE_AVIF_DETECTION`: enables AVIF support detection. When the file extension is omitted in the imgproxy URL and browser supports AVIF, imgproxy will use it as the resulting format;
+* `IMGPROXY_ENFORCE_AVIF`: enables AVIF support detection and enforces AVIF usage. If the browser supports AVIF, it will be used as resulting format even if another extension is specified in the imgproxy URL.
-When WebP support detection is enabled, please take care to configure your CDN or caching proxy to take the `Accept` HTTP header into account while caching.
+**📝Note:** imgproxy prefers AVIF over WebP. This means that if both AVIF and WebP detection/enforcement are enabled and the browser supports both of them, AVIF will be used.
+
+**📝Note:** When AVIF/WebP support detection is enabled, please take care to configure your CDN or caching proxy to take the `Accept` HTTP header into account while caching.
**⚠️Warning:** Headers cannot be signed. This means that an attacker can bypass your CDN cache by changing the `Accept` HTTP headers. Have this in mind when configuring your production caching setup.
diff --git a/process.go b/process.go
index 8ebe8e29..6d62594a 100644
--- a/process.go
+++ b/process.go
@@ -742,8 +742,11 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
po := getProcessingOptions(ctx)
imgdata := getImageData(ctx)
- if po.Format == imageTypeUnknown {
+ switch {
+ case po.Format == imageTypeUnknown:
switch {
+ case po.PreferAvif && imageTypeSaveSupport(imageTypeAVIF):
+ po.Format = imageTypeAVIF
case po.PreferWebP && imageTypeSaveSupport(imageTypeWEBP):
po.Format = imageTypeWEBP
case imageTypeSaveSupport(imgdata.Type) && imageTypeGoodForWeb(imgdata.Type):
@@ -751,7 +754,9 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
default:
po.Format = imageTypeJPEG
}
- } else if po.EnforceWebP && imageTypeSaveSupport(imageTypeWEBP) {
+ case po.EnforceAvif && imageTypeSaveSupport(imageTypeAVIF):
+ po.Format = imageTypeAVIF
+ case po.EnforceWebP && imageTypeSaveSupport(imageTypeWEBP):
po.Format = imageTypeWEBP
}
diff --git a/processing_options.go b/processing_options.go
index 4eee4e17..eb2767fd 100644
--- a/processing_options.go
+++ b/processing_options.go
@@ -154,6 +154,8 @@ type processingOptions struct {
PreferWebP bool
EnforceWebP bool
+ PreferAvif bool
+ EnforceAvif bool
Filename string
@@ -1033,6 +1035,11 @@ func defaultProcessingOptions(headers *processingHeaders) (*processingOptions, e
po.EnforceWebP = conf.EnforceWebp
}
+ if strings.Contains(headers.Accept, "image/avif") {
+ po.PreferAvif = conf.EnableAvifDetection || conf.EnforceAvif
+ po.EnforceAvif = conf.EnforceAvif
+ }
+
if conf.EnableClientHints && len(headers.ViewportWidth) > 0 {
if vw, err := strconv.Atoi(headers.ViewportWidth); err == nil {
po.Width = vw