Spring-boot: Range header does not work for resources that resolve to `war:` URLs

Created on 5 Sep 2018  路  6Comments  路  Source: spring-projects/spring-boot

Environment: Spring Boot 2.0.3 with WebMVC and embedded Tomcat 8.5.

When a request for a static resource includes a Range header and the resource resolves to a war: URL, the response is always 416 (Range Not Satisfiable).

I originally asked about this on StackOverflow, but later found the underlying cause via the debugger.

The cause is that HttpRange.toResourceRegion() fails to determine the length of the resource. (Or rather, the length returned is -1.) The reason for that is that since the resource's URL is not a file URL AbstractFileResolvingResource.contentLegth() tries opening a connection to the URL and calling getContentLength() on the connection, and WarURLConnection doesn't override URLConnection's default implementation of returning -1.

I'm not sure whether this would be considered a bug in Spring Boot or in embedded Tomcat, but the former seems the more appropriate place to file the initial bug report in this case.

I have a minimal project to reproduce the issue, which I'll submit a pull request for in spring-boot-issues.

invalid

Most helpful comment

The Tomcat issue is fixed for 9.0.13 and 8.5.35. (See https://bz.apache.org/bugzilla/show_bug.cgi?id=62687#c1.)

All 6 comments

Your StackOverlow describes pretty well what's going on.
In my opinion, there's nothing Spring Framework nor Spring Boot can do to improve the situation - if there's no way to know the content-length of the resource, then we can't handle range-requests.

Tomcat might be able to improve something here, but this might be a limitation tied to the fact that files are being streamed from an archive with no way to get the length of the stream without reading it first. You can search for existing issues or create a new one on https://bz.apache.org/bugzilla/.

Thanks!

but this might be a limitation tied to the fact that files are being streamed from an archive with no way to get the length of the stream without reading it first.

It's possible to get the length of the file without reading it from the archive. It's what the JDK's JarUrlConnection does. I think the problem is that org.apache.catalina.webresources.war.WarURLConnection doesn't override getContentLength() and getContentLengthLong() to delegate them to wrappedJarUrlConnection in the same way as it already does for getLastModified().

Thanks @wilkinsona !
@douglyuckling could you create an issue on the Tomcat tracker and link back to it here? This will be useful to other community members.

Finally got around to filing the bug on the Tomcat tracker: https://bz.apache.org/bugzilla/show_bug.cgi?id=62687

@douglyuckling Thanks. And thanks, too, for joining the dots with the last modified change. I'd completely forgotten that I'd raised that issue.

The Tomcat issue is fixed for 9.0.13 and 8.5.35. (See https://bz.apache.org/bugzilla/show_bug.cgi?id=62687#c1.)

Was this page helpful?
0 / 5 - 0 ratings