diff --git a/CHANGELOG.md b/CHANGELOG.md index 504ddb4d..1e049e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ - Add [extend_aspect_ratio](https://docs.imgproxy.net/latest/generating_the_url?id=extend-aspect-ratio) processing option. - (pro) Add [advanced smart crop](https://docs.imgproxy.net/latest/configuration?id=smart-crop) +### Change +- Make the `expires` processing option set `Expires` and `Cache-Control` headers. + ## [3.13.2] - 2023-02-15 ### Change - Remove color-related EXIF data when stripping ICC profile. diff --git a/options/processing_options.go b/options/processing_options.go index d0a64720..4afbf7d4 100644 --- a/options/processing_options.go +++ b/options/processing_options.go @@ -95,6 +95,8 @@ type ProcessingOptions struct { CacheBuster string + Expires *time.Time + Watermark WatermarkOptions PreferWebP bool @@ -826,6 +828,9 @@ func applyExpiresOption(po *ProcessingOptions, args []string) error { return errExpiredURL } + expires := time.Unix(timestamp, 0) + po.Expires = &expires + return nil } diff --git a/processing_handler.go b/processing_handler.go index ff2beaa4..aafc8299 100644 --- a/processing_handler.go +++ b/processing_handler.go @@ -55,10 +55,16 @@ func initProcessingHandler() { headerVaryValue = strings.Join(vary, ", ") } -func setCacheControl(rw http.ResponseWriter, originHeaders map[string]string) { +func setCacheControl(rw http.ResponseWriter, force *time.Time, originHeaders map[string]string) { var cacheControl, expires string var ttl int + if force != nil { + rw.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d, public", int(time.Until(*force).Seconds()))) + rw.Header().Set("Expires", force.Format(http.TimeFormat)) + return + } + if config.CacheControlPassthrough && originHeaders != nil { if val, ok := originHeaders["Cache-Control"]; ok && len(val) > 0 { cacheControl = val @@ -115,7 +121,7 @@ func respondWithImage(reqID string, r *http.Request, rw http.ResponseWriter, sta rw.Header().Set("Content-DPR", strconv.FormatFloat(po.Dpr, 'f', 2, 32)) } - setCacheControl(rw, originData.Headers) + setCacheControl(rw, po.Expires, originData.Headers) setVary(rw) setCanonical(rw, originURL) @@ -143,7 +149,7 @@ func respondWithImage(reqID string, r *http.Request, rw http.ResponseWriter, sta } func respondWithNotModified(reqID string, r *http.Request, rw http.ResponseWriter, po *options.ProcessingOptions, originURL string, originHeaders map[string]string) { - setCacheControl(rw, originHeaders) + setCacheControl(rw, po.Expires, originHeaders) setVary(rw) rw.WriteHeader(304) diff --git a/stream.go b/stream.go index 4b5ee445..08aebf8a 100644 --- a/stream.go +++ b/stream.go @@ -113,7 +113,7 @@ func streamOriginImage(ctx context.Context, reqID string, r *http.Request, rw ht rw.Header().Set("Content-Disposition", imagetype.ContentDisposition(filename, ext, po.ReturnAttachment)) } - setCacheControl(rw, map[string]string{ + setCacheControl(rw, po.Expires, map[string]string{ "Cache-Control": rw.Header().Get("Cache-Control"), "Expires": rw.Header().Get("Expires"), })