この質問では クエリ文字列またはルートパラメーターを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}}"}
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
});
};
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形式に変換するマッピングテンプレートを構成する必要があります。もちろんこれは汚い解決策ですが、今のところそれを行う唯一の方法だと思います。
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
@ 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つに二重引用符がある場合のケースも修正されます。
POSTリクエストContent-Type
はapplication/x-www-form-urlencoded
。 GETリクエストに似た値の長いクエリ文字列を取得するだけの場合は、このマッピング構文を使用します。
{
"body": "$input.body"
}
他のマッピングを追加することもできます。元の問題に対処するために省略しました。
ブログチュートリアルはこちらAPIを最初に実装したときに使用したものです。次に、ラムダ関数がクエリ文字列を解析し、データを他のプロセスに渡します。
この最小限の作業コードを見つけるのに少し時間がかかったので、共有する価値があると思う本当にシンプルなソリューションを見つけました。
コンテンツタイプ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.
}
これはラムダ統合で機能します。 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;
}
投稿された値の順序付けられた辞書を返す単純な関数:
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になるためです。
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
}
}