1. tanaken on Rails
  2. #038: Kamal v2, rate_limit, ..
2024-09-21 15:31

#038: Kamal v2, rate_limit, Parameters#expect

Summary

今回のエピソードでは、Kamalというアプリケーションデプロイツールのバージョン2、レイトリミットメソッド、そしてParameters#expectを用いたデータ処理の新機能が紹介されています。これらの変更は、より効率的で安全なアプリケーション開発に寄与することが期待されています。

Kamal2の導入
こんにちは、tanaken on Rails第38回です。
今週は3つのプレリクエストを紹介します。
1つ目、Kamal2 Compatible Configurationということで、
レールタイズに関する変更です。
Kamalというアプリケーションデプロイツールについて、
このバージョン2をレールズで使用するようになったというプレリクエストですね。
このKamalは以前のtanaken on Railsでも紹介しています。
アプリケーションデプロイツールで、
ドッカー環境の構築からアプリのデプロイ、
トラフィックの切り替えまでを自動的に行ってくれるものだという風に紹介されています。
これのバージョン2Kがリリースされていて、
それを使うようになったと。
このバージョン2Kでは、
オートSSLとマルチアプリケーションのデプロイが可能になるとのことですね。
レイトリミットメソッドの改善
続いて2つ目、
Add Ability to Use Multiple Rate Limits per Controllerということで、
アクションパックに関する変更です。
コントローラーに対して複数パターンのレイトリミットを設定できるようになりましたと。
どういうことじゃいということで、
前提としてまずレイトリミットメソッドについて紹介していきます。
レイトリミットメソッドは、
例えばセッションズコントローラーというものがあって、
クリエイトアクションがあるとしましょうと。
このアクションへのリクエストを3分間に10回までとしましょうという場合に、
クラスセッションコントローラーでレイトリミット10回ですね。
Within 3 Minutes。
3分の間オンリークリエイト。
クリエイトアクションだけ3分間で10回までというふうにしましょうみたいな、
そういう設定ができるというのがレイトリミットメソッドでございます。
なのでこの例だと3分間で11回目以降のリクエストが来たときは、
429 Too Many Requests のエラーになる。
エラーレスポンスを返すということですね。
これがレイトリミットメソッドです。
このレイトリミットメソッドなんですけれども、
リクエストの回数をコントローラーとアクションの組み合わせで、
キャッシュのキーとしてカウントしていると。
これはアクション設定しないケースこともできるので、
その場合はコントローラーに対してのカウントになるし、
コントローラーとアクションが指定されていれば、
その組み合わせでカウントするという感じになっておりまして、
例えば同じアクションに対して2種類以上のレイトリミットを設定するというふうにやると、
1回のリクエストの際に、
その種類分複数回カウントアップしちゃうというバグに近いかもしれないですね。
そういう挙動になっていましたと。
具体例が一周に記載されておりまして、
リクワイヤーバンドルインラインとかでジェムをこれ入れて、
テストがこれでみたいな色々書いてるんですけど、
大事なとこで言うとテストコントローラーというものがあります。
レイトリミットto2within1minute、レイトリミットto5within1hourという形で、
1分間に2回までという制限と、1時間で5回までという宣言、
この2つを同時に成り立たせたいというシーン、
そういう設定になっている、そういうつもりで設定を書いていると。
ありそうですよね。
短期間で何回までというのと、ちょっと長い間では合計何回までみたいな、
ありそうだなというユースケースだと思うんですけど、
この場合にですね、1回目のリクエストの時に、
まだレイトリミットには引っかからないんですけど、
レイトリミットメソッドの呼び出しが2回あるので、
このテストコントローラーに対して、まず1回カウントアップ、
1分間に2回までという条件に満たすかどうかのとこでカウントアップが1回入って、
その後、1時間の間に5回までを満たすかどうかでまたカウントアップが入っちゃって、
1回目のリクエストの段階で2回カウントアップみたいな感じになっちゃってるんですよね。
なのでリクエストが2回目来た時に、本来だとまだ1分間に2回まで、
連続でポンポンとリクエストがあってね、1分間に2回までっていうのでギリギリセーフなんですけど、
レイトリミットメソッドの呼び出しがすでに2回あるので、1回目の時に2回しちゃってるので、
2回カウントアップしちゃってて、リクエストが2回目の時には3回目のカウントアップに入っちゃうと、
で、Too Many Requests のレスポンスを返しちゃうよというので、
これってどうなんだろうねと、1個のコントローラーとアクションの組み合わせに対して、
レイトリミットが1個しか設定できないというのは、ちょっと不便なんじゃないかというのがありました。
で、今回のプレリクエストでは、レイトリミットメソッドにオプションでネイムというのを指定できるようにしています。
で、このネイムを含めたキャッシュキーによってリクエスト回数を管理するようになっているということで、
例えば具体的なコードで言うと、テストコントローラーで、
レイトリミット2 Within 1 Minute Name Short Term
レイトリミット5 Within 1 Hour Name Long Term とかっていう形で、
それぞれのレイトリミットに対して名前をつけてるんですよね。
1分間に2回の方はショートタームという名前をつけてて、
1時間に5回の方はロングタームという名前をつけてると。
この名前をつけることによって、それぞれの名前も含めてカウントするようになっているよということで、
複数種類のレイトリミットを指定することができるようになりましたと。
これはありがたい修正だなと思いましてピックアップしました。
Parameters#expectの新機能
さて、最後3つ目。
Add Parameters Sharp Expect to Safely Filter and Require Parameters ということで、
アクションパックに関する変更です。
より安全でより明示的なパラメータ処理の方法が導入されましたということで、
これまでのコントローラーにおけるパラメータの処理と言いますと、
リクワイヤーメソッドとパーミットメソッドを組み合わせる方法というのが一般的かと思います。
これ多分レールズガイドとかにも書いてあるかと思いますね。
多分レールズチュートリアルとかでもそういう記載をしてると思います。
例えば具体的には、params.require()symbolperson.permit()で
シンボル、ネイム、カンマ、シンボル、エイジ、
で、ハッシュの形でpets://シンボル、ネイムとかっていう形で、
これはパーソンというパラメータで、
名前とエイジ、ネイムとエイジとパーソンがペッツを持ってますよと、ペットですね。
そのペットはネイムというキーを持つハッシュのアレイになっているというような感じかな。
ネイムのハッシュのアレイじゃないか、ネイムのアレイかな。
ペットかな、多分そう。
そういうパラメータのフィルターというか、
パーソンは必要で、パーソンの中はネイムとエイジとペッツだけ許可しますよというようなパラメータ処理。
よく書きますよね。
これに対して、今回のプルンリクエストでは新たにexpectというメソッドが追加されています。
これは何かというと、これを使うことでより厳密で安全にパラメータを処理できるということで、
さっきの例ですね。
シンボルネイムというようなパラメータ処理の方法の場合、
ここで例えばですけど、パラメータにパーソンイコールほげほげみたいな文字列が渡ってきたとしましょうと。
純粋な文字列ですね。
本当はネイムとかエイジとか、それぞれのアトリビュートを持っているようなパラメータが来ることを想定しているんだけど、
パーソンイコール文字列みたいな形で来ちゃったと。
そういうハックをされたという場合に、
params.requirepersonの時点でストリングになっていて、
ストリングに対してpermitを呼ぶって感じになっちゃうんで、
ノーメソッドエラーになります。
そうすると、このノーメソッドエラーはサーバーエラーなので、
500エラーを返しますってことになりますね。
本来はパーソンイコール何らかの文字列っていうパラメータが悪いんですよね。
リクエストパラメータが悪いので、バットリクエストなんですよね。
400を返したいと。
なんだけれども現状は、このパラメータ処理の方法、
requirepermitを使ったパラメータ処理の方法だと500エラーになっちゃいますと。
もちろんやりようはいろいろあると思うんですけど、
よくある書き方でやると500エラーになっちゃいますよね。
そうではなくて、expectという今回導入したメソッドを使いましょう。
使い方としては、params.expectパーソンコロン大きいかぎかっこで、
シンボルネーム、シンボルエイジ、ペッツコロン、かぎかっこ、シンボルネームというような感じ。
これをやると、パーソンイコールほげほげみたいな文字列が来た場合に、
パーソンはネームとかエイジとかペッツを持っているパラメータであってくれというのが、
このexpectによって明示化されているので、
ストリングが来たときに、
アクションコントローラーコロンコロン、パラメータミッシングという例外をレイズします。
これで400エラーを返しましょうと。
そうなると、バットリクエストであることがちゃんと伝わりますよね。
こういった処理がすごい分かりやすくなりますよというので、
このexpectというメソッドを使いましょうということでした。
リクエストパラメータをより厳密に処理できるようになるというのは、
すごい嬉しいことだなと思ったのでピックアップしています。
あとは、チェンジログのほうに記載されていたのが、
リクエストパラメータからIDを取得するということはよくあると思います。
パラメータのパスにIDが含まれていたりとか、
パラメータで受け取ったりとか、
いろいろあると思うんですけど、
そういったケースでもexpectメソッドを使うとより厳密になるので、
ぜひ使ってねと言ってましたと。
例えばなんですけど、
params.requireidとかでやると、
これ僕も知らなかったんですけど、
これIDがアレイでも受け取れちゃうんですね。
IDに複数渡して、
ID括弧とかで複数渡してみたいなことができてしまうということなんですけど、
今回のparams.expectというメソッドを使うと、
expect括弧IDでやると、
ノンブランクなスカラーだけを受け取ることができますということで、
ノンブランクなんてニルじゃなかったり、空文字列じゃないとか、
かつハッシュとかアレイとかではない値を取得できると。
これができるとその後の処理の取り回しもしやすくなるなと。
正直params.requireidでも単一のIDの数字だけ来るというふうに期待、
そういう前提でアプリケーションコードを書いているケースも結構あるなと思ってて、
こういったより厳密なパラメータの処理ができると嬉しいなと思ってピックアップしました。
以上でございます。
今回はプルリクエストを3つ紹介しました。
1つ目はkamalというアプリケーションデプロイツールのバージョン2が使うようになったよという話と、
アクションパックに関して2つ、レイトリミットメソッドとパラメーターズエキスペクトメソッドの話をしました。
こんなところで今週は以上とします。
ではまた来週。バイバイ。
15:31

Comments

Scroll