Browse Source

add config fallback ttl to avoid default ttl when fallback response (#818)

* add config fallback ttl to avoid default ttl when fallback response

* Update docs/configuration.md

Co-authored-by: Sergey Alexandrovich <DarthSim@users.noreply.github.com>

* move FallbackTTL to loadFallbackImage

* rewrite ifelse

* Update imagedata/image_data.go

don't use config.FallbackTTL on header to get TTL on the response

Co-authored-by: Sergey Alexandrovich <DarthSim@users.noreply.github.com>

* Update processing_handler.go

don't use config.FallbackTTL on header to get TTL on the response

Co-authored-by: Sergey Alexandrovich <DarthSim@users.noreply.github.com>

* rename FallbackTTL to FallbackImageTTL

* Update processing_handler.go

* Fix linter errors

Co-authored-by: Sergey Alexandrovich <DarthSim@users.noreply.github.com>
dcanob 3 years ago
parent
commit
f37d027f4f
5 changed files with 27 additions and 12 deletions
  1. 2 0
      .gitignore
  2. 3 0
      config/config.go
  3. 1 0
      docs/configuration.md
  4. 13 10
      imagedata/image_data.go
  5. 8 2
      processing_handler.go

+ 2 - 0
.gitignore

@@ -7,3 +7,5 @@ tmp/
 .gitmodules
 docker-base
 docs/sitemap.txt
+.env
+.devcontainer/*

+ 3 - 0
config/config.go

@@ -107,6 +107,7 @@ var (
 	FallbackImagePath     string
 	FallbackImageURL      string
 	FallbackImageHTTPCode int
+	FallbackImageTTL      int
 
 	DataDogEnable bool
 
@@ -247,6 +248,7 @@ func Reset() {
 	FallbackImagePath = ""
 	FallbackImageURL = ""
 	FallbackImageHTTPCode = 200
+	FallbackImageTTL = 0
 
 	DataDogEnable = false
 
@@ -402,6 +404,7 @@ func Configure() error {
 	configurators.String(&FallbackImagePath, "IMGPROXY_FALLBACK_IMAGE_PATH")
 	configurators.String(&FallbackImageURL, "IMGPROXY_FALLBACK_IMAGE_URL")
 	configurators.Int(&FallbackImageHTTPCode, "IMGPROXY_FALLBACK_IMAGE_HTTP_CODE")
+	configurators.Int(&FallbackImageTTL, "IMGPROXY_FALLBACK_IMAGE_TTL")
 
 	configurators.Bool(&DataDogEnable, "IMGPROXY_DATADOG_ENABLE")
 

+ 1 - 0
docs/configuration.md

@@ -242,6 +242,7 @@ You can set up a fallback image that will be used in case imgproxy is unable to
 * `IMGPROXY_FALLBACK_IMAGE_PATH`: the path to the locally stored image
 * `IMGPROXY_FALLBACK_IMAGE_URL`: the fallback image URL
 * `IMGPROXY_FALLBACK_IMAGE_HTTP_CODE`: the HTTP code for the fallback image response. When set to zero, imgproxy will respond with the usual HTTP code. Default: `200`
+* `IMGPROXY_FALLBACK_IMAGE_TTL`: a duration (in seconds) sent via the `Expires` and `Cache-Control: max-age` HTTP headers when a fallback image was used. This feature is disabled by default.
 * `IMGPROXY_FALLBACK_IMAGES_CACHE_SIZE`: <i class='badge badge-pro'></i> the size of custom fallback images cache. When set to `0`, the fallback image cache is disabled. 256 fallback images are cached by default.
 
 ## Skip processing

+ 13 - 10
imagedata/image_data.go

@@ -79,22 +79,25 @@ func loadWatermark() (err error) {
 }
 
 func loadFallbackImage() (err error) {
-	if len(config.FallbackImageData) > 0 {
+	switch {
+	case len(config.FallbackImageData) > 0:
 		FallbackImage, err = FromBase64(config.FallbackImageData, "fallback image")
-		return
-	}
-
-	if len(config.FallbackImagePath) > 0 {
+	case len(config.FallbackImagePath) > 0:
 		FallbackImage, err = FromFile(config.FallbackImagePath, "fallback image")
-		return
+	case len(config.FallbackImageURL) > 0:
+		FallbackImage, err = Download(config.FallbackImageURL, "fallback image", nil, nil)
+	default:
+		FallbackImage, err = nil, nil
 	}
 
-	if len(config.FallbackImageURL) > 0 {
-		FallbackImage, err = Download(config.FallbackImageURL, "fallback image", nil, nil)
-		return
+	if FallbackImage != nil && err == nil && config.FallbackImageTTL > 0 {
+		if FallbackImage.Headers == nil {
+			FallbackImage.Headers = make(map[string]string)
+		}
+		FallbackImage.Headers["Fallback-Image"] = "1"
 	}
 
-	return nil
+	return err
 }
 
 func FromBase64(encoded, desc string) (*ImageData, error) {

+ 8 - 2
processing_handler.go

@@ -49,6 +49,7 @@ func initProcessingHandler() {
 
 func setCacheControl(rw http.ResponseWriter, originHeaders map[string]string) {
 	var cacheControl, expires string
+	var ttl int
 
 	if config.CacheControlPassthrough && originHeaders != nil {
 		if val, ok := originHeaders["Cache-Control"]; ok {
@@ -60,8 +61,12 @@ func setCacheControl(rw http.ResponseWriter, originHeaders map[string]string) {
 	}
 
 	if len(cacheControl) == 0 && len(expires) == 0 {
-		cacheControl = fmt.Sprintf("max-age=%d, public", config.TTL)
-		expires = time.Now().Add(time.Second * time.Duration(config.TTL)).Format(http.TimeFormat)
+		ttl = config.TTL
+		if _, ok := originHeaders["Fallback-Image"]; ok && config.FallbackImageTTL > 0 {
+			ttl = config.FallbackImageTTL
+		}
+		cacheControl = fmt.Sprintf("max-age=%d, public", ttl)
+		expires = time.Now().Add(time.Second * time.Duration(ttl)).Format(http.TimeFormat)
 	}
 
 	if len(cacheControl) > 0 {
@@ -246,6 +251,7 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) {
 		if config.FallbackImageHTTPCode > 0 {
 			statusCode = config.FallbackImageHTTPCode
 		}
+
 		originData = imagedata.FallbackImage
 	}