Uploaded image for project: 'Confluence Data Center'
  1. Confluence Data Center
  2. CONFSERVER-57501

JPG Image Caching Not Working for IE, Edge and Firefox - ETag is missing from resource

      Problem Statement

      Image caching is crucial for reducing load times to improving overall user experience. However, JPG caching is not functioning well with JPG images on certain browsers i.e. IE, Edge and Firefox. Looking closer into the header attributes, we see that the ETag attribute is not being added to the resource during reload. Hence, the JPG images have to be requested to the server on every page reload.

      Expected Behavior

      All image files should be cached and retrieved from the cache resource instead of having to requesting from the server directly every page reload.

      Actual Behavior

      JPG files are requested from the server on every page reload.

        1. chrome.har.zip
          5.85 MB
        2. edge.har.zip
          5.90 MB
        3. firefox.har.zip
          3.26 MB
        4. internet-explorer.har.zip
          5.56 MB
        5. opera.har.zip
          5.80 MB
        6. safari.har.zip
          5.78 MB

            [CONFSERVER-57501] JPG Image Caching Not Working for IE, Edge and Firefox - ETag is missing from resource

            Hi guys,

            we found a work around by fixing the image effects plugin (version 2.0.2). We use a confluence standard method which inserts the "ETag" and "last-modified" into the response header. At least in our browsers (IE11 and Firefox ESR version) the jpgs are cached.

             

            Plugin ImageEffectsPlulgin-2.0.2
            Class com.atlassian.confluence.image.effects.ImageFilterServlet
            Method     private void writeTransformToResponse(final HttpServletRequest request, final HttpServletResponse response, final boolean isPreview, final TransformContext context) throws IOException {
                    Function<BufferedInputStream, HttpServletResponse> responseSupplier = (imageBufferStream) -> {
                        response.setContentType(getMimeTypeFrom(imageBufferStream));
                        //fix https://jira.atlassian.com/browse/CONFSERVER-54780
                        response.setHeader("X-Content-Type-Options", "nosniff");
             
                        if (isPreview) {                 response._setHeader_("Cache-Control", *_PREVIEW_CACHE_CONTROL_HEADER_*);             }

                        // This method writes the "ETag" and "Last-Modified" in the Response-Header
                        com.atlassian.plugin.servlet.util.LastModifiedHandler.checkRequest(request, response, new Date(context.getLastModified()));
                        return response;
                    };
             
                    final InputStream cacheStream = config.isDisableCache() ? null :
                            imageCache.get(context.getAttachmentId(), context.getCacheEntryName(), context.getLastModified());
                    if (cacheStream != null)

            {             eventPublisher._publish_(*new* *DiskCacheUsageEvent*(*true*, context.*getCacheEntryName*()));             *_log_*._debug_("Using the cached value");             *copyToResponse*(cacheStream, responseSupplier);         }

            else {
                        eventPublisher.publish(new DiskCacheUsageEvent(false, context.getCacheEntryName()));
                        final boolean responseSent = transformAndRespond(context, buildEffectsList(request, isPreview), response);
                        if (!responseSent)

            Unknown macro: {                *final* InputStream imageStream = context.*getImageSupplier*()._get_();                *if* (imageStream != *null*) {                     *_log_*._debug_("Sending back the original");                     *copyToResponse*(imageStream, responseSupplier);                 }            }

                    }
                }
             

             

             Hope this helps you.

             

            Best regards,

             

            Stefan

             

            Stefan Bitzer added a comment - Hi guys, we found a work around by fixing the image effects plugin (version 2.0.2). We use a confluence standard method which inserts the "ETag" and "last-modified" into the response header. At least in our browsers (IE11 and Firefox ESR version) the jpgs are cached.   Plugin ImageEffectsPlulgin-2.0.2 Class com.atlassian.confluence.image.effects.ImageFilterServlet Method     private void writeTransformToResponse ( final HttpServletRequest request, final HttpServletResponse response, final boolean isPreview, final TransformContext context) throws IOException {         Function<BufferedInputStream, HttpServletResponse> responseSupplier = (imageBufferStream) -> {             response. setContentType ( getMimeTypeFrom (imageBufferStream));             //fix https://jira.atlassian.com/browse/CONFSERVER-54780             response. setHeader ("X-Content-Type-Options", "nosniff");               if (isPreview) {                 response._setHeader_("Cache-Control", *_PREVIEW_CACHE_CONTROL_HEADER_*);             }              // This method writes the "ETag" and "Last-Modified" in the Response-Header             com.atlassian.plugin.servlet.util.LastModifiedHandler. checkRequest ( request , response , new Date( context .getLastModified()));             return response;         };           final InputStream cacheStream = config. isDisableCache () ? null :                 imageCache. get (context. getAttachmentId (), context. getCacheEntryName (), context. getLastModified ());         if (cacheStream != null ) {             eventPublisher._publish_(*new* *DiskCacheUsageEvent*(*true*, context.*getCacheEntryName*()));             *_log_*._debug_("Using the cached value");             *copyToResponse*(cacheStream, responseSupplier);         } else {             eventPublisher. publish ( new DiskCacheUsageEvent ( false , context. getCacheEntryName ()));             final boolean responseSent = transformAndRespond (context, buildEffectsList (request, isPreview), response);             if (!responseSent) Unknown macro: {                *final* InputStream imageStream = context.*getImageSupplier*()._get_();                *if* (imageStream != *null*) {                     *_log_*._debug_("Sending back the original");                     *copyToResponse*(imageStream, responseSupplier);                 }            }         }     }      Hope this helps you.   Best regards,   Stefan  

              Unassigned Unassigned
              syong@atlassian.com Sean Yong
              Affected customers:
              2 This affects my team
              Watchers:
              2 Start watching this issue

                Created:
                Updated: