内容长度大于 1024 时的 AWS api 网关错误

AWS api gateway error when content length is greater than 1024

当我尝试请求 aws api 网关时,当响应内容长度大于 1024 时浏览器失败。 即请求在小数据上成功,而不是大数据。

错误时的响应头:

Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Cache-Control, Authorization, Credentials, UserId
Access-Control-Allow-Methods:GET,PUT,POST,DELETE,OPTIONS
Access-Control-Allow-Origin:*
Cache-Control:no-store, no-cache, must-revalidate, proxy-revalidate
Connection:keep-alive
Content-Encoding:gzip
Content-Type:application/json; charset=utf-8
Date:Thu, 24 Aug 2017 15:47:53 GMT
ETag:W/"2e66-gh/gyPzUq3KxiQAslibZJg"
Expires:0
Pragma:no-cache
Surrogate-Control:no-store
Transfer-Encoding:chunked
Vary:X-HTTP-Method-Override, Accept-Encoding
X-Powered-By:Express

出现错误时在控制台中显示响应

https://********/v1/centers net::ERR_CONTENT_DECODING_FAILED  (chrome)

SyntaxError: JSON.parse: Unexpected end of data at line 1 column 1 of the JSON data (Firefox)

成功时的响应头

access-control-allow-headers →Origin, X-Requested-With, Content-Type, Accept, Cache-Control, Authorization, Credentials, UserId
access-control-allow-methods →GET,PUT,POST,DELETE,OPTIONS
access-control-allow-origin →*
cache-control →no-store, no-cache, must-revalidate, proxy-revalidate
content-length →838
content-type →application/json; charset=utf-8
date →Fri, 25 Aug 2017 04:44:52 GMT
etag →W/"346-I99yuNQRDTf/UvarDA7kdw"
expires →0
pragma →no-cache
status →200
surrogate-control →no-store
vary →Accept-Encoding
via →1.1 1ed35878396a5c073c88fd1b51c4f47a.cloudfront.net (CloudFront)
x-amz-cf-id →WEICithhcr5_GNYeXUUa35lvUIsicZCOnyPLdfbLm54hlS6sO3rIcw==
x-amzn-remapped-connection →keep-alive
x-amzn-remapped-content-length →838
x-amzn-remapped-date →Fri, 25 Aug 2017 04:44:51 GMT
x-amzn-requestid →224537d0-8950-11e7-ab72-bfe4c43d695f
x-cache →Miss from cloudfront
x-powered-by →Express

Api 网关

的 Swagger json 定义
{
  "swagger": "2.0",
  "info": {
    "version": "2017-08-23T06:36:43Z",
    "title": "ProxyResourceForFsApi"
  },
  "host": "**********",
  "basePath": "/v1",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "options": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            },
            "headers": {
              "Access-Control-Allow-Origin": {
                "type": "string"
              },
              "Access-Control-Allow-Methods": {
                "type": "string"
              },
              "Access-Control-Allow-Headers": {
                "type": "string"
              }
            }
          }
        }
      },
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {}
      }
    }
  },
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}

相同的请求在来自服务器的数据较少时成功,在来自服务器的数据较大时失败。

第一个提示在这里:ERR_CONTENT_DECODING_FAILED

这个失败的响应是这样的:

Content-Encoding:gzip

"decoding" 错误是关于编码解码失败。

但这有点让人分心。真正的问题在这里:

Transfer-Encoding:chunked

API 网关显然不支持分块 transfer-encoding 响应。这有时也称为 "streaming response."

为什么错误阈值是 1024?您的 back-end 在开始 gzip 响应之前似乎使用 1024 作为最小大小。这可能不是问题,除非当您的 back-end 决定它需要 gzip 响应时,它也会切换到流式响应。

没有流式传输成功的响应:

x-amzn-remapped-content-length →838

分块 transfer-encoding 的流式响应未指定 content-length。

解决方案将涉及说服您的 back-end 不要流式传输其响应,这可能意味着说服它不要 gzip 响应。

这可以在 back-end 上完成,但可能有一个简单的解决方法:

在集成请求中,添加值为 'identity' 的 HTTP header Accept-Encoding' 单引号是必需的,因为 header 值是一个表达式,我们需要告诉 API 网关它是一个文字字符串。