謎のInternal server error
https://example.com/v1/?n=[name]
みたいな感じに、API Gatewayでn
パラメータを受けて、lambdaで処理する仕組みを作ったら、n
パラメータに"a&z" (URL Encode: "a%26z")みたいな"&"を含むデータを渡すと謎のInternal server error出てハマった。
- https://example.com/v1/?n=a%26z のResponse
{
message: "Internal server error"
}
ClowdWatchLogにはsignatureがどうのこうののエラーが。
- ClowdWatchLog
Execution failed due to configuration error:
The request signature we calculated does not match the signature you provided.
Check your AWS Secret Access Key and signing method.
Consult the service documentation for details.
原因
サポートに問い合わせたところ、以下の回答が。
The error is because the query string “a%26z” is decoded as “a&z” by CloudFront viz. the URL Encoded form. So, the API Gateway gets the query string as “a&z”. Now, when the invocation URL to lambda is being created it appends the Query String given in Integration Request of that resource. Now, the URL is
similar to “https://lambda..amazonaws.com/2015-03-31/functions//invocations?name=a%26z” but while calculating the signature [1] it treats as invalid because “/invocations?name=a%26z” is not a valid lambda invocation URL. The correct Lambda invocation URL is explained in this doc [2].
Moving forward, if you want to use a%26z to your backend then the correct way is to pass it like “a%2526z” In query string and have a body mapping template.
[1]. http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
[2]. http://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#w2ab1c67c12c49c11
知識のなさと英語力のなさでいまいち原因を理解できていないが(英語とAWS得意な誰か解説してください)、2重URLエンコードして %2526 にすればエラーにならないということは理解できた。Lambda内で一度URL Decodeしないといけないが。
解決
2重URLエンコードするのと同じようなものだが、結局、データをすべてBASE64でエンコードしてLambdaでDecodeすることにした。
疑問
既に多くの人がここではまっている気がするんだけど、ググっても全然情報ないのはなぜ?