首页 > 解决方案 > 为什么 Range 标头不适用于使用嵌入式 Tomcat 从 Spring Boot WAR 托管的静态资源?

问题描述

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

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

仅就上下文而言,所讨论的静态文件是一个.mp4视频,浏览器使用Range标头请求该视频,因为该文件被一个video元素引用。

在调试器中单步执行,我看到原因是HttpRange.toResourceRegion()无法确定资源的长度。(或者更确切地说,返回的长度是-1。)原因是由于资源的 URL 不是文件 URL,它会尝试打开到 URLgetContentLength()的连接并调用连接,并且WarURLConnection不会覆盖 returnURLConnection的默认实现-1

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

或者也许它实际上适用于其他所有人?也许我错过了一些神奇的 Spring 配置?(我怀疑这与 Spring Boot 的自动配置有关,但我应该在这里提一下,因为我正在将非 Boot 应用程序迁移到 Boot,所以我现在已经禁用了大部分功能。)

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

标签: springspring-mvcspring-bootembedded-tomcat-8

解决方案


我相信我已经想通了。事实证明,我所做的事情可能与大多数人的做法略有不同,并且(我认为)Spring Boot 中的一个错误在这种情况下会表现出来。

具体来说,我从 WAR 中托管这些资源,而不是从类路径中托管,因为 Spring Boot 这些天似乎鼓励。在我看来,无法确定war:URL 的内容长度这一事实是 Spring Boot 和/或嵌入式 Tomcat 中的一个错误。

修复只是将视频资源从src/main/webapp/videos/to移动src/main/resources/static/videos/并相应地更新我的资源处理程序注册表配置(例如addResourceLocations("/videos/")become addResourceLocations("classpath:/static/videos/"))。

我计划使用 Spring Boot 提交错误报告,当我这样做时我会链接到这里。

编辑:这是错误报告


推荐阅读