为什么Range标头不适用于使用嵌入式Tomcat从Spring Boot WAR托管的静态资源?

时间:2018-08-31 00:41:42

标签: spring spring-mvc spring-boot embedded-tomcat-8

我有一个使用WebMVC和嵌入式Tomcat 8.5的Spring Boot 2.0 WAR,并且在WAR中托管我的静态资源。

对包含Range: bytes=0-的静态资源的请求因HTTP 416(范围无法满足)而失败,而没有Range标头的相同请求也可以正常工作。

就上下文而言,所涉及的静态文件是.mp4视频,浏览器使用Range标头请求该视频,因为该文件是由video元素引用的。

逐步进入调试器,我发现原因是HttpRange.toResourceRegion()无法确定资源的长度。 (或者,返回的长度为-1。)原因是由于资源的URL不是文件URL,因此它尝试打开与该URL的连接并在该连接上调用getContentLength(),然后{{ 1}}不会覆盖WarURLConnection返回URLConnection的默认实现。

我想称它为Spring和/或嵌入式Tomcat中的错误,但是如果是这种情况,我觉得现在其他人已经报告了它(并且我找不到任何证据)。我在这里做一些不寻常的事情吗?

也许它实际上对其他所有人都有效?也许我错过了一些神奇的Spring配置? (我怀疑这与Spring Boot的自动配置有关,但是我要在这里提到的是,在我将非Boot应用程序迁移到Boot时,我暂时禁用了其中的大部分功能。)

我意识到我可以通过“手动”处理此资源请求(并在必要时使用-1的自定义实现)来解决此问题,但看来我不必这样做。似乎应该立即使用即可。

1 个答案:

答案 0 :(得分:2)

我相信我已经解决了。事实证明,我在做的事情与大多数人可能略有不同,并且(在我看来)Spring Boot中也存在一个错误,这种情况在这种情况下会显现出来。

具体来说,我最近从WAR而不是从类路径托管这些资源,因为Spring Boot似乎鼓励了这些日子。我认为无法确定war: URL的内容长度,这是Spring Boot和/或嵌入式Tomcat中的错误。

解决方法只是将视频资源从src/main/webapp/videos/移到src/main/resources/static/videos/并相应地更新我的资源处理程序注册表配置(例如addResourceLocations("/videos/")变成了addResourceLocations("classpath:/static/videos/"))。

我计划通过Spring Boot提交一个错误报告,当我这样做时将链接到这里。

编辑:这里是the bug report