Amazon web services AWS Api网关代理压缩“;无效的块类型";

Amazon web services AWS Api网关代理压缩“;无效的块类型";,amazon-web-services,gzip,aws-api-gateway,Amazon Web Services,Gzip,Aws Api Gateway,我将Api网关端点设置为HTTP\U代理,只要不提供Accept Encoding:gzip头,它就可以正常工作。然后它失败了。似乎Api网关正在对响应执行“某些操作”,使其在接收端无法识别 这就是我所看到的: 将请求直接发送到代理后端会按预期工作(例如,curl--compressed成功完成) 使用curl--compressed(和其他方式)通过Api网关发送请求会导致“无效块类型” 来自代理服务器的响应是17514字节,而通过Api网关,它已被放大到31506字节。这反映在内容长度标题

我将Api网关端点设置为
HTTP\U代理
,只要不提供
Accept Encoding:gzip
头,它就可以正常工作。然后它失败了。似乎Api网关正在对响应执行“某些操作”,使其在接收端无法识别

这就是我所看到的:

  • 将请求直接发送到代理后端会按预期工作(例如,
    curl--compressed
    成功完成)
  • 使用
    curl--compressed
    (和其他方式)通过Api网关发送请求会导致“无效块类型”
  • 来自代理服务器的响应是17514字节,而通过Api网关,它已被放大到31506字节。这反映在
    内容长度
    标题中
  • Api网关包含带有旧(正确)值的
    x-amzn-Remapped-Content-Length
    头,因此它似乎知道它对响应做了什么
API方法配置为HTTP代理,如下所示:

aws apigateway get-method --rest-api-id xxxxx --resource-id yyyyy --http-method POST

{
  "requestModels": {
    "application/json": "MyRequestModel"
  },
  "authorizationType": "CUSTOM",
  "apiKeyRequired": false,
  "httpMethod": "POST",
  "methodIntegration": {
    "passthroughBehavior": "WHEN_NO_MATCH",
    "cacheKeyParameters": [],
    "requestParameters": {},
    "uri": "http://myproxy/api/v1/resource",
    "httpMethod": "POST",
    "requestTemplates": {},
    "cacheNamespace": "zzzzz",
    "type": "HTTP_PROXY"
  },
  "requestValidatorId": "xyxyxyxy",
  "authorizerId": "zyzyzyzyz"
}
据我所知,这里没有任何东西代表Api网关指示任何映射。该UI也不指示任何响应映射

在测试Api时,我看到以下内容:

  • 响应标题包括
    “内容长度”:“17514”
    ,这是预期值
  • 从日志来看,端点响应体和方法响应体似乎是相同的,尽管手动比较gzip数据的两个乱码ascii表示有点困难。两个
    内容长度
    标题也相同
在测试期间,重新映射的内容长度值在任何地方都不可见,
x-amzn-remapped-content-length
标题也不可见。这让我怀疑这可能是Cloudfront做的

我通过“执行api”和这个api的自定义域映射得到了相同的结果


有什么建议吗?

正如Michael在他的一条(非常有用的)评论中所怀疑的那样-这确实是API网关将我的gzip流视为UTF-8编码文本并对其重新编码的情况。考虑到这是一个没有设置集成响应映射的端点,API网关将以任何方式处理我的响应似乎非常违反直觉,但文档中提到了这一点

解决方案是告诉API网关,对于这个REST API,
application/json
内容类型是“二进制数据”。这会导致API网关在未经处理的情况下传递响应。指示REST API对Cloudformation执行此操作本身有点像兔子洞,解决方案如下:

RestApi:
  Type: 'AWS::ApiGateway::RestApi'
  Properties:
    Name: !Sub 'agraNcdx${Environment}'
    BinaryMediaTypes:
      - 'application~1json'

我不相信CloudFront会进行任何转换,但您可以通过将API部署为区域而不是边缘优化,将其完全排除在循环之外。API网关一度不支持
传输编码:分块的
响应,当看到
Accept Encoding:gzip
时,您的源站可能会切换到它,因为分块传输编码将允许您的源站流化gzip响应,而不是缓冲它,直到gzip响应的
内容长度
已知为止。什么是
invalid block type
——来自curl的控制台错误或实际响应正文中的错误消息?“invalid block type”是当响应无法有效解压缩时curl对
curl--compressed
所说的。将结果传送到
gunzip
也不起作用。我认为我之前确定的解决方法是在集成请求中设置一个静态请求头
Accept Encoding:identity
,但我还没有找到答案,我也不确定API网关和流式响应的当前状态。您所描述的行为听起来并不熟悉,因此即使实现了目的,它也可能不是最佳解决方案,因为事情可能已经发生了变化。它所做的事情听起来像是将二进制有效负载强制转换为UTF-8,这可能会替换任何识别为无效字符的内容(并非所有的八位字节序列都代表有效的UTF-8)使用� Unicode替换字符,具有字节
0xEF
0xBF
0xBD
,肯定会扰乱您的gzip流。非常感谢@Michael sqlbot!这确实是响应的utf-8编码-请参阅下面我自己的答案。>“但文档中提到了它”。你能给我指一下那个文档页面吗?我想我也遇到了同样的问题。事实上,我不确定它的功能有多突出-他们只是在binaryMediaTypes文档中提到“默认情况下RestApi只支持utf-8文本”,例如:和(搜索“utf-8编码文本”)