AWS Serverless Lambda未编码的字符

时间:2018-05-31 07:50:01

标签: amazon-web-services aws-lambda serverless-framework

我在aws lambda上有一个简单的无服务器功能

QA团队决定创建一个用字符" ^"进行测试的卷曲请求。 当它没有编码时,即:

curl -X GET   'https://lambda.com/call?id=inva^lid'

因此,此调用甚至无法访问我的代码,因为它不会返回任何内容。 空白,没有。

任何想法如何解决这个问题? 在lambda? ApiGateway? CloudFront的?

任何想法都会很棒!

谢谢!

详细卷曲请求:

*   Trying 54.230.159.190...
* TCP_NODELAY set
* Connected to example.com (1.1.1.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):


* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.example.com
*  start date: Feb 26 00:00:00 2018 GMT
*  expire date: Mar 26 12:00:00 2019 GMT
*  subjectAltName: host "example.com" matched cert's "example.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fb1cc00a400)
> GET /call?id=inva^lid HTTP/2
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: application/json
> Cache-Control: no-cache
> Postman-Token: b730c1f2-b8ab-4eeb-b097-99f7d812434a
> api-key: xxxxxxxxxxxxxxxxxxxxxx
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 400
< content-length: 0
< date: Thu, 31 May 2018 12:38:54 GMT
< x-cache: Error from cloudfront
< via: 1.1 xxxxxx.cloudfront.net (CloudFront)
< x-amz-cf-id: -Kn-xxxxxx==
<
* Connection #0 to host example.com left intact

现在我在日志中看到了这一点&#34;来自cloudfront的错误&#34;

所以任何想法如何解决?

现在使用--http1.1

进行相同的通话
*   Trying 1.1.1.1...
* TCP_NODELAY set
* Connected to example.com (1.1.1.1) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):

* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=*.example.com
*  start date: Feb 26 00:00:00 2018 GMT
*  expire date: Mar 26 12:00:00 2019 GMT
*  subjectAltName: host "example.com" matched cert's "example.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
> GET /call?id==inva^lid HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: application/json
> Cache-Control: no-cache
> Postman-Token: b730c1f2-b8ab-4eeb-b097-99f7d812434a
> api-key: xxxxxxxxx
>
< HTTP/1.1 400 Bad Request
< Content-Length: 0
< Connection: keep-alive
< Date: Thu, 31 May 2018 14:37:26 GMT
< X-Cache: Error from cloudfront
< Via: 1.1 xxxxxxx.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: xxxxxxxxx-J60xxc0TI4MOjQ==
<
* Connection #0 to host example.com left intact

1 个答案:

答案 0 :(得分:2)

您可以忽略X-Cache: Error from CloudFront的任何特定含义,因为它是CloudFront为其处理的任何请求添加的标准标头,其中HTTP响应代码为> = 400.CloudFront基础架构处理请求的传输一些其他服务,包括API网关边缘优化端点和S3传输加速(您可以通过尝试与未启用传输加速功能的存储桶进行加速连接来生成相同的标头)。它本质上意味着“CloudFront处理了这个请求,而某些东西不起作用” - 但它并没有给出一个关于究竟是什么的提示,因为错误可能是CloudFront的内部或外部,并且此标题将存在在这两种情况下。

为了缩小范围,我做了一些进一步的测试。事实证明,CloudFront对查询字符串参数中的^字符没有任何问题。通过CloudFront分布和自定义原点确认,此位置中的此角色不是问题。

但是API Gateway扼杀了它。

使用区域API端点(不使用CloudFront进行传输)确认这一点,API网关在^上阻塞并返回......几乎没有。

< HTTP/1.1 400 Bad Request
< Date: Thu, 31 May 2018 15:54:59 GMT
< Content-Length: 0
< Connection: keep-alive
<

有一个类似的记录案例......

  

任何请求URL查询字符串都不支持纯文本管道符(|),并且必须进行URL编码。

     

https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html

将未转义的管道字符放入查询字符串会触发完全相同的行为,因此这似乎是API网关的限制 - 它拒绝此字符并将其称为“错误请求”,这意味着客户端请求格式错误

API网关似乎与^具有相同的问题。

在这两种情况下,拒绝都发生在API网关基础架构的早期阶段,不仅您的代码看不到它......现在这么早,请求甚至无法进入API端点的CloudWatch日志。

基于此,可能它可能甚至不计入您的throttling limits,因为API Gateway可能已经停止解析请求,甚至在将其与您的API关联之前,特别是&lt; /猜测取代。

如果您将^作为%5E进行网址转义,则API网关没有问题。事实上,它甚至可以正确解码它并显示日志中的值:

Method request query string: {id==inva^lid}

所以我说你的QA团队发现了API网关的问题 - 你需要在查询字符串中url-escape ^字符。但是它返回了一个有效的HTTP错误代码......只是没有响应主体。