以下の内容はhttps://patorash.hatenablog.com/entry/2024/08/22/151156より取得しました。


Lambda Web Adapterを使ってSinatraを動かす

Railsで運用されていたアプリをSinatraで実装し直した上でサーバーレスで動かしたかったのでやってみました。 こちらのRailsアプリも長いことメンテされておらず、RubyのバージョンもRailsのバージョンも古すぎた…。

作ったもの

シンプルなWebAPIを作った(Rails + PostgreSQLSinatra + DynamoDB)

構成

サーバーレスで動かすのを大前提としていたので、API Gateway + Lambda + DynamoDBで考えてました。 なんかうっすらLambdaでsinatra動かしてみた、みたいな記事を見たことがあった記憶があったので、まぁできるんだろうと安易に考えておりました(結構ハマった)

ぶっちゃけLambdaもAPI GatewayもDynamoDBもほぼ初めてだったので(なんかのチュートリアルでよくわからず使ったことはある)、めちゃめちゃ手探りでした。

DynamoDBクライアント

DynamoDBのクライアントはdynamoidを使いました。dynamoidはActiveRecord風にDynamoDBが操作できるライブラリです。

github.com

その他?

特にないだろうか…。AWSもSAA持ってるくせして実際に動かすのはよくわからないのでSAMでデプロイとかもよくわからず、とりあえずマネジメントコンソールから作業しまくってました。動けばええんやで(後で自動化すればええんや)

LambdaでSinatraを動かそうとしたが…

「Lambda Sinatra」でググると、Qiitaの記事がヒットしました。

qiita.com

Lambda Web Adapterというものがあることを知ったのでこれを使ってみることにしました。 やり方は上記の記事に書いてある通りなのですが、Lambdaで動かすDockerイメージを作成しました。 そして、イメージにタグを定義してECRにDockerイメージをpush。

AWSマネジメントコンソールからLambdaの関数を作成し、ECRからイメージを指定しました。

ここまでは、上記の記事のままでできました。ここからが分からない…。API Gatewayの設定を適当にしてみたものの、全く上手く動かなかったので、一旦放置…。

そもそも定義したLambda関数がちゃんと動くのかどうかを検証しないと、Lambdaが原因なのか、API Gatewayの設定が原因なのかがわからない。 Lambda関数の詳細画面のテストタブから、テストできることに気付いたので、そこから各APIに対してリクエストを試して、動作することを確認。問題なし。逆にAPI Gatewayの設定で何が悪いのかがわからん…。再度API Gatewayと向き合うことに。

API Gatewayの設定するもうまく動かない

API GatewayでHTTP APIを作成。ステージをProdという名前で作成。統合で、定義したLambda関数を指定。そしてデプロイ。 それで https://[API ID].execute-api.[リージョン].amazonaws.com/[ステージ名(Prod)] というURLが発行されます。

発行されたURLに対してアクセスするも、not foundと言われる…。ただ、このnot foundというメッセージは私がSinatraで定義していた、パスが見つからない場合に呼ばれているものだったので、明らかにSinatraは動いている。 なんとなく、 /Prod というステージ名をSinatraがパスとして理解してnot foundになっているんじゃないか?という推測したんだけれど、これをどう修正すればいいのかがわからず、半日くらい潰してしまいました。

パラメータマッピングでパスを上書きしよう!

統合の設定のところで、パラメータマッピングという項目があり、こちらでパラメータを追加したり上書きしたりできるとあったので確認したところ、pathを上書きすることができると分かったので、一旦staticで / で上書きしたところ、Sinatraの正常なリクエストが返ってくることを確認。絶対に推測通りだなと思ったのですが、どうやったら /[ステージ名] を除外できるのかがわからず。候補で出てくるものの内容を以下のサイトで確認。

docs.aws.amazon.com

リクエストパス $request.path または ${request.path} ステージ名を含まないリクエストパス。

これだ!と思い、 path$request.path で上書きするように設定したところ、動きました!🎉

pathを$request.pathで上書き!

API Gatewayに定義するroutesは2つでよい

Sinatraでルーティングは決まっているので、それに合わせてroutesをいくつも定義しないといけないかなと思ってたのですが、$defaultという特殊なルーティングができるようです。

どのルーティングにも当てはまらない時にルーティングされるやつ

どのルーティングにも当てはまらないときに $default にルーティングされるため、最低1つはルーティングを定義しておかないといけないみたいだったので、 / を定義し、/$default のどちらにも統合で同じLambda関数を指定すればOK。これで、全てのリクエストはSinatraに渡されて評価されるので、見つからないときはnot foundが返るし、Sinatraで定義されているルートならば、その処理が実行されます。

/と$defaultを定義

まとめと感想

LambdaでSinatraを動かすこと自体は簡単なのだけれど、API Gatewayとの接続方法で結構ハマりましたが、やり方さえ分かればどうってことないですね!これで私もようやくサーバーレスチョットデキルと言える!!




以上の内容はhttps://patorash.hatenablog.com/entry/2024/08/22/151156より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14