【发布时间】:2017-08-29 09:34:55
【问题描述】:
我在 2 个 EC2 实例(暂存环境和生产环境)上部署了一个 Spring Boot 应用程序。我有一个用于下载文件的端点。它看起来像这样(应用程序是用 Kotlin 编写的):
@PostMapping("/download")
open fun download(@RequestBody request: DownloadRequest, servletResponse: HttpServletResponse) {
val file = getByteArray(request.fileId)
servletResponse.outputStream.write(file)
servletResponse.contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE
servletResponse.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"${request.fileId}.zip\"")
}
当我在登台机器上执行下载请求时,一切都很好。我取回文件,响应设置了标题。这些是我可以在 Postman 中看到的标题:
Cache-Control →no-cache, no-store, max-age=0, must-revalidate
Connection →keep-alive
Content-Disposition →attachment; filename="345412.zip"
Content-Length →11756
Content-Type →application/octet-stream
Date →Tue, 04 Apr 2017 09:04:19 GMT
Expires →0
Pragma →no-cache
X-Application-Context →application:8081
X-Content-Type-Options →nosniff
X-Frame-Options →DENY
X-XSS-Protection →1; mode=block
当我在生产中执行相同的请求时,响应正文包含文件内容,但我手动设置的 2 个标头“Content-Type”和“Content-Disposition”丢失了:
Cache-Control →no-cache, no-store, max-age=0, must-revalidate
Connection →keep-alive
Content-Length →56665
Date →Tue, 04 Apr 2017 09:06:45 GMT
Expires →0
Pragma →no-cache
X-Application-Context →application:8081
X-Content-Type-Options →nosniff
X-Frame-Options →DENY
X-XSS-Protection →1; mode=block
两台机器都在 Docker 容器中部署了完全相同的 JAR。这两个调用都是直接针对 EC2 实例进行的,使用它们的私有 IP,因此不涉及 ELB。 2 个实例的配置是相同的,我在 AWS 控制台中没有发现任何差异。
你知道这可能是什么原因吗? EC2 中是否有可以防止某些 HTTP 标头在响应中被发回的设置?我找不到任何理由说明为什么在一种情况下将标头发回,而在另一种情况下则不发回。
【问题讨论】:
-
我想知道您的请求是否真的达到了
download方法。调用 prod 主机时从服务器返回的 HTTP 代码是什么? -
@Trein 暂存和生产状态码均为 200。我的请求怎么可能达不到
download方法?我正在返回响应正文中的文件内容。 -
你是对的。我错过了您说响应正文带有文件内容的部分。在两种环境之一中是否有任何环境变量设置不同? Spring Boot 有几个内置的杠杆和开关,它们可能会导致分级/产品差异。
-
@Trein 两个环境之间唯一与 Spring 相关的配置差异是数据库配置属性(spring.datasource.url、用户名和密码)。我在两个环境中都使用默认值。
标签: java spring-boot amazon-ec2 http-headers kotlin