web-dev-qa-db-ja.com

パラメーターをPOSTからAmazon API GatewayからAWS Lambdaに渡す方法

この質問では クエリ文字列またはルートパラメーターをAmazon API GatewayからAWS Lambdaに渡す方法

aPIゲートウェイを使用してクエリ文字列パラメーターをAWSラムダにマップする方法を示します。同じことをしたいのですが、クエリ文字列の代わりにPOST値をマッピングします。

{
    "values": "$input.params()"
}

動作しませんでしたが、実際のフォームデータは表示されません。ところで私は以下を使用して投稿しています:

application/x-www-form-urlencoded

私はラムダ関数から応答を得るので、ラムダを正常に呼び出していることがわかりますが、私の問題はPOST paramsがどこにも表示されないことです。 Lambda側で取得したすべてをダンプします。ここにあります。

 {"values":"{path={}, querystring={}, header={Accept=*/*, Accept-Encoding=gzip, deflate, Accept-Language=en-US,en;q=0.8, Cache-Control=no-cache, CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, CloudFront-Viewer-Country=US, Content-Type=application/x-www-form-urlencoded, Origin=chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop, Postman-Token=7ba28698-8753-fcb1-1f48-66750ce12ade, Via=1.1 6ba5553fa41dafcdc0e74d152f3a7a75.cloudfront.net (CloudFront), X-Amz-Cf-Id=sc8C7dLcW0BHYopztNYrnddC0hXyFdBzHv0O9aWU1gKhd1D_J2HF3w==, X-Forwarded-For=50.196.93.57, 54.239.140.62, X-Forwarded-Port=443, X-Forwarded-Proto=https}}"}
40
ecorvo

R7kamuraによる良い答え。さらに、すべてのケースで機能するapplication/x-www-form-urlencodedのわかりやすく堅牢なマッピングテンプレートの例を次に示します(POSTを想定)。

{
    "data": {
        #foreach( $token in $input.path('$').split('&') )
            #set( $keyVal = $token.split('=') )
            #set( $keyValSize = $keyVal.size() )
            #if( $keyValSize >= 1 )
                #set( $key = $util.urlDecode($keyVal[0]) )
                #if( $keyValSize >= 2 )
                    #set( $val = $util.urlDecode($keyVal[1]) )
                #else
                    #set( $val = '' )
                #end
                "$key": "$val"#if($foreach.hasNext),#end
            #end
        #end
    }
}

入力を変換します

name=Marcus&email=email%40example.com&message=

{
    "data": {
                "name": "Marcus",
                "email": "[email protected]",
                "message": ""
    }
}

Lambdaハンドラーは次のように使用できます(これはすべての入力データを返します)。

module.exports.handler = function(event, context, cb) {
  return cb(null, {
    data: event.data
  });
};
66
Marcus Whybrow

AWS Lambdaが受信できるように統合設定でマッピングテンプレートを設定することにより、リクエストボディデータを有効なJSON形式に変換できます。

現在、Amazon API Gatewayはまだapplication/x-www-form-urlencodedを公式にサポートしていないようですが、avilewinは a solution をAWSフォーラムに投稿しました。マッピングテンプレートでは、 Velocity Template Language(VTL) を使用できます。そのため、application/x-www-form-urlencoded形式を有効なJSON形式に変換するマッピングテンプレートを構成する必要があります。もちろんこれは汚い解決策ですが、今のところそれを行う唯一の方法だと思います。

20
r7kamura

Lambdaプロキシ統合を有効にする場合 enter image description here

POST本文は次の場所から入手できます。

event['body']['param']

GETパラメータとヘッダーは、

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
16
Jonathan

APIゲートウェイテンプレートを使用して、パラメーターをJSONに変換できます。 https://forums.aws.Amazon.com/thread.jspa?messageID=673012&tstart=0#673012

または、QueryStringパーサーパッケージを使用して、ラムダ関数自体でこれを行うことができます。 https://www.npmjs.com/package/qs

var qs = require('qs');
var obj = qs.parse('a=c');  // { a: 'c' } 

Amazonがこのような機能の組み込みサポートを追加する場合、それを使用しますが、それまでは、何かがうまくいかない場合はよりクリーンでデバッグしやすいため、2番目の方法を個人的に好みます。

2017年7月更新

デフォルトでそれをサポートするプロキシ統合を使用できます: http://docs.aws.Amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda .html

11
advncd

@ markus-whybrow回答の拡張:

{
        #foreach( $token in $input.path('$').split('&') )
            #set( $keyVal = $token.split('=') )
            #set( $keyValSize = $keyVal.size() )
            #if( $keyValSize >= 1 )
                #set( $key = $util.urlDecode($keyVal[0]) )
                #if( $keyValSize >= 2 )
                    #set( $val = $util.urlDecode($keyVal[1]) )
                #else
                    #set( $val = '' )
                #end
                "$key": "$util.escapeJavaScript($val)"#if($foreach.hasNext),#end
            #end
        #end
    }

これにより、「データ」が削除され、値の1つに二重引用符がある場合のケースも修正されます。

5
Mark Sergienko

POSTリクエストContent-Typeapplication/x-www-form-urlencoded。 GETリクエストに似た値の長いクエリ文字列を取得するだけの場合は、このマッピング構文を使用します。

{
    "body": "$input.body"
}

他のマッピングを追加することもできます。元の問題に対処するために省略しました。

ブログチュートリアルはこちらAPIを最初に実装したときに使用したものです。次に、ラムダ関数がクエリ文字列を解析し、データを他のプロセスに渡します。

3
openwonk

この最小限の作業コードを見つけるのに少し時間がかかったので、共有する価値があると思う本当にシンプルなソリューションを見つけました。

コンテンツタイプapplication/x-www-form-urlencodedでデータを送信する一般的なフォームがある場合は、「Lambdaプロキシ統合」フラグを立てるだけで、Node.jsで解析できるエンコードされたフォームデータがevent.bodyにあります。 querystringネイティブモジュール。

const querystring = require('querystring')

function handler (event, context, callback) {
  // Read form data.
  const { user, pass } = querystring.parse(event.body)

  // Follows your code to handle request.
}
1
Gianluca Casati

これはラムダ統合で機能します。 POSTリクエスト本文が.

{
   "name" : "Hello",
   "address" : "Cool place" 
}

次のようにアクセスできます。

if (event.body !== null && event.body !== undefined) {
   let body = JSON.parse(event.body)
   let name = body.name;
   let address = body.address;
}

詳細はこちら: http://docs.aws.Amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

1
Dodi

投稿された値の順序付けられた辞書を返す単純な関数:

import urllib
from collections import OrderedDict
postdata = ''

def GetPostData(body):
    #postdata = OrderedDict()
    postdata = {}
    for items in body.split('&'):
        vals = items.split('=')
        postdata[vals[0]] = urllib.parse.unquote(vals[1])
    return postdata

#Testing it out:
#Assume you get body from event['body'] or body = event.get['body']
body = 'text=This%20works%20really%20well%21%245123%21%403%2146t5%40%2341&anotherkey=isawesome23412%201%21%403%21%40312'

postdata = GetPostData(body)
print(postdata['text'])
#returns 'This works really well!$5123!@3!46t5@#41'
print(postdata['anotherkey'])
#returns 'isawesome23412 1!@3!@312'

投稿されたアイテムが見つからない場合のキーエラーを回避するには、代わりにvalue = postdata.get( '')を使用する必要があります。キーが存在しない場合、値はNoneになるためです。

0
Arvin Amir

POSTからすべてのボディをLambda関数に送信する場合は、Integration Request

{
    "values": $input.json('$')
}

本体から独自の構造を構築する場合は、次を実行します。

{
    "values": {
        "body-param1": $input.json('body-param1'),
        "others": {
            "body-param2": "$input.json('body-param2')",
        }
    }
}

ここで、body-param1は数値で、body-param2は文字列です。

ヘッダーを送信する場合は、次を実行します。

{
    "headers": {
        #foreach($param in $input.params().header.keySet())
            "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext), #end
        #end
    }
}
0
Camilo Ortegón