web-dev-qa-db-ja.com

httpエンドポイントを使用してラムダのHTTPリクエスト(ヘッダー、クエリ文字列、Cookie、本文)オブジェクトにアクセスします

ラムダコードでwithからリクエストヘッダーと本文の値にアクセスする方法を確認しようとしています。リクエストの本文がJSON形式の場合、自動的に解析され、イベントオブジェクトで利用できるようになります。

Lambda内の任意のタイプの着信「Content-Type」リクエストの完全なクエリ文字列、リクエスト本文、リクエストヘッダー(Cookie)にアクセスするにはどうすればよいですか?


以下の編集は、関連する場合と関連しない場合がある質問を解決するために私が収集した情報です。必要に応じて無視してください。


編集:

SEに関する既存の質問を確認しました ここ および ここ 。このように thread$input.json('$')を使用するとうまくいくはずです。上記のリンクからの回答は、APIゲートウェイがデフォルトでリクエスト内のJSONを認識しているようで、マッピングテンプレートを構成せずにeventオブジェクトで利用できるようにするため、すでに古くなっていると思います。

提案どおりにマッピングを設定しても、うまくいきません。リクエストヘッダー情報は含まれていません。

構成方法のスクリーンショットを次に示します。

enter image description here


enter image description here

「headers」キーは空白の値を返します。 $input.params('$')または"$input.params('$')"を使用するとエラーが発生します。


編集2

メソッドリクエストでヘッダーを定義しようとしました。ラムダ内でまだUser-Agent値を取得していません。

enter image description here


編集3

APIゲートウェイで次のテンプレートマッピングを使用しました

{
    "request": $input.json('$'),
    "headers": "$input.params()"
}

およびラムダの以下のコード

context.succeed("event.key32:"+JSON.stringify(event, null, 2) );

そして、APIゲートウェイによって生成された応答はこれを示しています enter image description here

レスポンスの「headers」値を見ると、AWS-SDK/APIゲートウェイ/ cloudfrontがHTTPクライアントから受信したすべてのヘッダーを削除しているように見えますか? $ input.params()。headerによって返されるJSONからの全文は次のとおりです。

header={CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, Content-Type=application/json, Via=1.1 5d53b9570d94ce920abbd471.cloudfront.net (CloudFront), 1.1 95eea7baa7ec95c9a41eca9e3ab7.cloudfront.net (CloudFront), X-Amz-Cf-Id=GBqmObLRy6Iem9bJbVPrrW1K3YoWRDyAaMpv-UkshfCsHAA==, X-Forwarded-For=172.35.96.199, 51.139.183.101, X-Forwarded-Port=443, X-Forwarded-Proto=https}}

ヘッダーにUser-Agent文字列はありませんが、上のスクリーンショットに示すように、RESTクライアントによって送信されました。興味深いことに、クエリ文字列全体が利用可能になっています。わからないこれがそれにアクセスするための意図された方法である場合。

12
user3526

リクエストヘッダーには、$input.params('header-name')を使用してアクセスできます。

驚いたことに、上記のコードではUser-Agentヘッダーにアクセスできません。あなたはそれを取得するためにフープに続いて the をジャンプする必要があります:

$context.identity.userAgent

リクエストの本文/ペイロードには、次のコードを使用してアクセスできる必要があります。詳細参照 ここここ および ここ

{
   "reqbody": "$input.path('$')"
}

リクエストの本文がJSONであると予想されるかどうかはまだ明確ではありません。 this postによると、リクエストはUTF-8として扱われることに注意する必要があります。


現在2つあるようです バグ

  1. 「User-Agent」ヘッダーが欠落しているか、AmazonAPIによって削除されています。
  2. ヘッダー値に二重引用符( ")が含まれている場合、ラムダ関数は実行されません。(cloudwatchログにログエントリが表示されません代わりに、httpレスポンスボディには以下が含まれます。

    {
       "Type": "User",
       "message": "Could not parse request body into json."
    }
    

Amazon APIで失敗するリクエストの例 enter image description here

キャッシュ用のETagメカニズムを実装できるようにするには、これを修正する必要があると思います。

参照:

Etagは二重引用符で囲む必要があります。ブラウザは、この正確な値をIf-None-Matchヘッダーを介して送り返すことが期待されており、これがAmazonAPIが機能しない場所です。

ETagの構文?

HTTP:etagの最大長

http://gsnedders.com/http-entity-tags-confusion

4
user3526

「Content-Type」が送信されない場合、AWS APIGatewayはデフォルトで「application/json」に設定されているようです: https://forums.aws.Amazon.com/thread.jspa?threadID=215471

したがって、「application/json」のマッピングテンプレートを定義するだけです。

2
inakiabt

テンプレートマッピングで必要な情報を取得し、それらをLambda関数に返送する必要があります。これは、Lambda関数に情報を送信するために使用したテンプレートの1つです。

{
   "params" : "$input.params()",
   "content-type-value" : "$input.params().header.get('Content-Type')",
   "body" : "$input.json('$')",
   "request-id": "$context.requestId",
   "method": "$context.httpMethod",
   "resource": "$context.resourcePath",
   "id": "$input.params('id')" //This is a path parameter in my case
}

同じことを行うことも、params.path.idにアクセスすることもできます(私の場合も同様です)。これが リンク ドキュメントへのリンクです。

乾杯、

1
e-nouri

参照された質問の1つへの回答で使用したマッピングテンプレートを更新して、userAgentプロパティを含めました。

{
  "method": "$context.httpMethod",
  "body": $input.json('$'),
  "userAgent": "$context.identity.userAgent",
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "queryParams": {
    #foreach($param in $input.params().querystring.keySet())
    "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "pathParams": {
    #foreach($param in $input.params().path.keySet())
    "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end

    #end
  }  
}

テンプレートの詳細な説明はこちらから入手できます: http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from- api-gateway /

1
kennbrodhagen