【问题标题】:HTTP headers not returned on EC2EC2 上未返回 HTTP 标头
【发布时间】: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


【解决方案1】:

通过首先编写响应标头然后响应正文解决了该问题:

@PostMapping("/download")
open fun download(@RequestBody request: DownloadRequest, servletResponse: HttpServletResponse) {
    val file = getByteArray(request.fileId)
    servletResponse.contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE
    servletResponse.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"${request.fileId}.zip\"")
    servletResponse.outputStream.write(file)
}

如果您先开始编写正文,则可能无法正确设置标题。我仍然不确定为什么这只在生产机器上复制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 2016-08-14
    • 2018-08-02
    • 2013-05-30
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    相关资源
    最近更新 更多