web-dev-qa-db-ja.com

POST AmazonAPIゲートウェイへのURLエンコードされたフォーム

サードパーティのサービスから通知を受信するためのWebhookを作成しています。サードパーティのサービスは、データをPOST with content type application/x-www-form-urlencoded

ただし、同じエラーが発生します。

{"message": "Could not parse request body into json: Unrecognized token \'name\': was expecting \'null\', \'true\', \'false\' or NaN\n at [Source: [B@456fe137; line: 1, column: 6]"}

次のcurl呼び出しでエラーを再現できます。

% curl -v -X POST -d 'name=Ignacio&city=Tehuixtla' https://rl9b6lh8gk.execute-api.us-east-1.amazonaws.com/prod/mandrillListener
*   Trying 54.230.227.63...
* Connected to rl9b6lh8gk.execute-api.us-east-1.amazonaws.com (54.230.227.63) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.execute-api.us-east-1.amazonaws.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> POST /prod/mandrillListener HTTP/1.1
> Host: rl9b6lh8gk.execute-api.us-east-1.amazonaws.com
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Length: 27
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 27 out of 27 bytes
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Content-Length: 180
< Connection: keep-alive
< Date: Thu, 28 Jan 2016 12:29:40 GMT
< x-amzn-RequestId: cd4d9232-c5ba-11e5-a158-b9b39f0b0599
< X-Cache: Error from cloudfront
< Via: 1.1 1915b8b49d2fbff532431a79650103eb.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: cxU2_b5DzIw4M_n3hJBFXTu9AVRBL3GpbQqUId9IxgS004DfLYqYmg==
<
* Connection #0 to Host rl9b6lh8gk.execute-api.us-east-1.amazonaws.com left intact
{"message": "Could not parse request body into json: Unrecognized token \'name\': was expecting \'null\', \'true\', \'false\' or NaN\n at [Source: [B@d92973b; line: 1, column: 6]"}

ボディを二重引用符で囲むと、正常に機能します。

% curl -v -X POST -d '"name=Ignacio&city=Tehuixtla"' https://rl9b6lh8gk.execute-api.us-east-1.amazonaws.com/prod/mandrillListener
*   Trying 54.230.227.19...
* Connected to rl9b6lh8gk.execute-api.us-east-1.amazonaws.com (54.230.227.19) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.execute-api.us-east-1.amazonaws.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> POST /prod/mandrillListener HTTP/1.1
> Host: rl9b6lh8gk.execute-api.us-east-1.amazonaws.com
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Length: 29
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 29 out of 29 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 6
< Connection: keep-alive
< Date: Thu, 28 Jan 2016 12:33:20 GMT
< x-amzn-RequestId: 50610606-c5bb-11e5-b140-5d837ffe26ed
< X-Cache: Miss from cloudfront
< Via: 1.1 a670cda0e28541e40881b95b60c672b7.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: mCLKL4eOnpUMd15IXQZw0RStJHw9Vdf3ivdCl37dcmno2JFOfxw0Vg==
<
* Connection #0 to Host rl9b6lh8gk.execute-api.us-east-1.amazonaws.com left intact
"true"%

ランバには1行しかありません。

context.succeed('true');

どうすればAPIゲートウェイが本体をjsonとして扱わないようにすることができますか?

テンプレートマッピングに関するドキュメントを試しましたが成功しませんでした。変数をまったく使用せずに、静的テンプレートに変換しようとしました。すべての場合において、エラーは私のコードに到達する前に発生します。

9
Jonas Fagundes

マッピングテンプレートを次のように設定してみてください。

_{
  "body" : $input.json('$')
}
_

これにより、文字列がjsonに変換され、ラムダに渡されます。

Amazonから docs$input.json(x)関数はJSONPath式を評価し、結果をJSON文字列として返します。

11
Vor

これは完全に関連しているわけではありませんが、Amazon API Gatewayを初めて使用する場合は、他の人が提案しているように、マッピングテンプレートを追加した後、APIを(再)デプロイする必要があるとは思いませんでした。以前にAPIをデプロイした場合)。ここに投稿された提案を行った後でも、なぜこのエラーが発生し続けるのか理解できなかったため、これには多くのデバッグ時間がかかりました。

AWSコンソールを使用している場合、

  • aPI内の任意のペインに移動します
  • 上部の[アクション]メニューを選択します
  • メニューから[DeployAPI]を選択し、関連するステージを選択して確認します
3
hayduke

フォームデータを機能させるためのマッピングテンプレートはかなり複雑です。ここに要点があります: https://Gist.github.com/ryanray/668022ad2432e38493df

また、Slackと統合する方法の例がある私が書いたこの投稿を見ることができます(それらのフックはフォームデータとしてPOSTをAPIゲートウェイに送信します): http:// www.ryanray.me/serverless-slack-integrations

1
Ryan

API Gatewayで、リソースのPOSTメソッドを選択し、を選択します統合リクエストおよびapplication/x-www-form-urlencodedの新しいマッピングテンプレートを作成します。

#set($body = $input.path('$'))
#set($jsonString = $util.urlencode($body))
#set($json = $util.parsejson($jsonString))

{
  "body" : $json,
}

または、URLエンコードされた文字列を渡すこともできます。

#set($body = $input.path('$'))
{
  "body" : "$body",
}

ラムダ内のJSONをURLデコードして解析します。

0
Lukas Nevosad