[MGNLIMG-317] Incorrect Content-Range Header when using ranged request Created: 05/Jul/23  Updated: 05/Jul/23

Status: Open
Project: Imaging
Component/s: None
Affects Version/s: 3.5.6, 3.5.7, 3.5.8
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Theocharis Koktsidis Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

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


Attachments: PNG File workaround-disable-range-requests.png    
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[X]* Steps to reproduce, expected, and actual results filled
[X]* Affected version filled

 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

  1. Issue a request to /.imaging using Range header
  2. 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.

  1. 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.
  2. 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()


Generated at Mon Feb 12 02:14:21 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.