Details
-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
3.5.6, 3.5.7, 3.5.8
-
None
-
None
-
Magnolia Version 6.2.27 up to 6.2.35
Imaging module 3.5.6 up to 3.5.8, possibly earlier version as well
Description
While trying to setup Azure Front Door to serve cached images from imaging module we noticed that FD was unable to serve images served under /.imaging path in Magnolia. The root cause of that was identified as an incorrect Content-Range header value. Observe the faulty value below (Note: asset content length in the example below was ~65000)
Steps to reproduce
- Issue a request to /.imaging using Range header
- Observe invalid Content-Range response header
> GET /.imaging/focalpoint/_WIDTH_x_HEIGHT_/{{YOUR_DAM_JCR_ASSET}} HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.84.0
> Accept: */*
> Range: bytes=0-1000000
* Mark bundle as not supporting multiuse
< HTTP/1.1 206
< X-Magnolia-Registration: Registered
< Cache-Control: max-age=600, public
< Expires: Wed, 05 Jul 2023 11:17:36 GMT
< ETag: 0CF063449C58CAE7CD3D4E28E1BAAAA1C265B2A6
< Accept-Ranges: bytes
< Content-Range: bytes 0-1000000/2147483647
< Content-Type: image/webp;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 05 Jul 2023 11:07:37 GMT
Expected results
Observe the results after implementation of workaround
> GET /.imaging/focalpoint/_WIDTH_x_HEIGHT_/dam/{{YOUR_DAM_JCR_ASSET}} HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.84.0
> Accept: */*
> Range: bytes=0-1000000
* Mark bundle as not supporting multiuse
< HTTP/1.1 206
< X-Magnolia-Registration: Registered
< Cache-Control: max-age=600, public
< Expires: Wed, 05 Jul 2023 11:20:31 GMT
< ETag: A583335CC1450A3D131BD8FE2FF9BB4599268724
< Accept-Ranges: bytes
< Content-Range: bytes 0-64065/64066
< Content-Type: image/webp;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 05 Jul 2023 11:10:31 GMT
Actual results
You can find an output from the curl command under Steps To Reproduce
Workaround
There are two possible solutions for this.
- Disabling ranged requests
Add the configuration as shown on screenshot under config workspace @ /server/filters/range
Note that this will disable ranged requests entirely severely reducing the efficiency of Azure FD when delivering large files. - Manually setting Content-Range headers on response.
You need a custom ServletImageResponse that can set content length on the response. Provide your own ImagingServlet implementation that uses your custom ServletImageResponse. Additionally you need to provide custom AbstractImageStreamer implementations as below:public class CustomCachingImageStreamer<P> extends CachingImageStreamer<P> { public CustomCachingImageStreamer(Session session, CachingStrategy<P> cachingStrategy, ImageStreamer<P> delegate, SystemContext systemContext) { super(session, cachingStrategy, delegate, systemContext); } @Override protected void serve(Property binary, ImageResponse imageResponse) throws IOException { final InputStream in; try { in = binary.getBinary().getStream(); } catch (RepositoryException e) { throw new IllegalStateException("Can't get InputStream from " + binary); } final String contentType; try { contentType = binary.getParent().getProperty(JcrConstants.JCR_MIMETYPE).getString(); } catch (RepositoryException e) { throw new IllegalStateException("Can't get content-type from " + binary); } imageResponse.setMediaType(MediaType.parse(contentType)); //--- START OF CHANGE ContentLengthImagingServletResponse castImageResponse = (ContentLengthImagingServletResponse) imageResponse; try { castImageResponse.setContentLength((int) binary.getLength()); } catch (RepositoryException e) { throw new IllegalStateException("Can't get content-length from " + binary); } // --- END OF CHANGE final OutputStream out = imageResponse.getOutputStream(); IOUtils.copy(in, out); IOUtils.closeQuietly(in); } }
Development notes
The root cause of the issue seems to be that no length is set on the ServletImageResponse. This is going through the info.magnolia.cms.filters.RangeSupportFilter that sets the default value of Content-Range header because range values are not specifically provided in case of the imaging servlet. Have a look at RangeSupportFilter#processRange()