Edited at

ブラウザからAWS Lambda Functionを呼び出して何かさせたい

ブラウザからJSを使ってAPI Gateway経由させてリクエストを処理させる方法に関しては記事を見つけたんですが

そんなめんどくさいことをしたくない()という超ものぐさ思考

やってみて思ったのは、Lambdaを起動して何かをさせるだけならURL一発で動くものが作れるという、いい時代になったなあ、っていう小学生並みの感想が浮かぶやつだった(何)

あとはまあ、IoT Buttonとかあの辺と同じぐらいの気軽さを、ブラウザからアクセスするやり方でやってみたかったんですよ。


注意

セキュリティとか知らんがな状態なので、URL非公開にするとか、自衛は必要かと思う。

まあ個人でやるとかそのレベルを想定していて、実際にできちゃったから記事にしてみた次第です。

そもそも重要な場面ではちゃんとセキュリティとか考慮してね!


何ができたの


  • URLのみでAPI Gatewayへリクエストを送信(してちゃんと受理される)できた

  • GETリクエストを投げると、Lambdaの実行結果が返ってくるようにできた

  • GETリクエストにパラメータを持たせて、その内容をLambdaに渡して処理ができた

たぶんこの辺ができれば、簡単な処理をさせたいんだけどわざわざサーバ用意するのもなってあたりは半分ぐらいは実現できるんじゃないかなーーー


どうやったの

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-on-demand-https-example-configure-event-source_1.html

これに従って作っていくと、LambdaとAPI Gatewayがセットで作れるので、あとはブラウザからURL叩いた時にリクエストを受理できるように調整すると、いい具合にできる。

筆者はPythonを使っているので、Pythonのブループリントを利用したけど、内容としては検索で引っかかるどのブループリントを使っても同じ内容っぽい。

とはいうものの、これだけだと役に立たなさすぎる記事が出来上がるので、つまづきポイントを解説しようと思う


Lambdaにどのようにリクエストが渡るのか

API Gatewayに対して、GETリクエストを送信した場合、Lambdaの起動時に以下のようなデータが、eventに入った状態で起動します


event

{

…略
"queryStringParameters": {
"param1": "hogerahogera",
"param2": "asdftyuio"
}
…略
}

paramXXがGETリクエストに含まれるクエリになります。

なので、Lambda関数のハンドラは lambda_function.lambda_handler として


lambda_function.py

def lambda_handler(event, context):

payload = event["queryStringParameters"]
param1 = payload["param1"]
param2 = payload["param2"]

のような感じにしてやると、パラメータがそのまま取得できます。便利。


API Gateway側で処理されるレスポンスの形式を作る

当然なんですけど、Lambda関数で return True とかやってもAPI Gatewayは認識してくれないので、ブラウザ側にはステータスコード400が返ったりするわけです

API Gatewayに返すレスポンスとしては


  • statusCode

  • body

  • headers

の3つが必要のようです。

まあ見てわかると思うんですけど、Lambdaの実行結果をbodyに入れて、成功か失敗かは、StatusCode200か400か、みたいなごく必要最低限の実装でよい場合は、


lambda_function.py

def create_response(err,result):

if err:
status = "400"
else:
status = "200"

return {
'statusCode': status,
'body': result,
'headers': {
'Content-Type': 'application/json',
},
}


みたいな感じでやればよいと。雑だけどこれで動く。


URL直でAPI Gatewayに処理を受理させる方法

(正直ガバガバすぎて怒られそうだけど)できます

API Gatewayのページに飛ぶと、Lambdaのブループリントで作ったAPIが既に表示されていると思います。

このAPIのページに入って、メソッドの実行についてANYになっている部分に移動します。

クライアント→メソッドリクエスト→統合リクエスト→Lambda関数

クライアント←メソッドレスポンス←統合レスポンス←Lambda関数

と表示される画面。

メソッドリクエストの設定をします。


  • 認証:なし

  • リクエストの検証:必要に応じて設定する

  • APIキーの必要性:False

にします。

URLクエリ文字列パラメータの設定で、

クエリ文字列の追加から、GETリクエストに含まれるクエリの設定をします。

必須のチェックを入れると、上記のリクエストの検証を有効にしていると、必須チェックを実施してくれます。

これで、(セキュリティ的には問題ありだが)ブラウザからURLに対してリクエストして、受理されるようになりました。


それにしてもセキュリティがガバガバすぎるのでは?

筆者はLambda関数の内部で、正当なリクエストかどうかのチェックを設けました

(そのぐらいならすぐできるわ、って思って…超雑なだけなんだけどさ)


APIのデプロイ

各APIのページの アクション→APIのデプロイ でデプロイ先のステージを指定してデプロイすればOK

左ペインにあるステージ → デプロイ先のステージを選択すると、URLが表示されているので、このURLに対して、

https://~~~~/ステージ/リソースのところに表示されているAPIの階層

でアクセスできるようになります。


筆者が作ったもの

AWS EC2の起動ボタン

サーバに上げて動かすほどじゃないけどこの機能がほしい、みたいな場面だったのでAPI Gateway → Lambda は最適じゃねえかな!って思った。

起動ボタンのHTML自体はローカルにおいておくという方法が使えるし。