私の以前の回答は機能しますが、すべてのリクエストを遅くする必要がある場合により適しています。それ以来、ケースバイケースでのみレート制限をオンにできるソリューションを考え出す必要があり、次の構成を思いつきました。知っておくべき重要なニュアンスがあるため、これを使用する前に必ず回答全体を読んでください。
location / {
if (-f somewhere/sensible/LIMIT) {
echo_sleep 1;
# Yes, we need this here too.
echo_exec /proxy$request_uri;
}
echo_exec /proxy$request_uri;
}
location /proxy/ {
internal;
# Ultimately, all this goes to a Django server.
proxy_pass http://django/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
}
重要な注意: さまざまなパスでスラッシュの有無によって違いが生じます。たとえばproxy_pass http://django
、末尾にスラッシュがない場合、上記のコードの行と同じことはしません。
動作原理は単純です。ファイルsomewhere/sensible/LIMIT
が存在する場合、一致location /
するリクエストは次に進む前に 1 秒間一時停止されます。したがって、私のテスト スイートでは、ネットワークのスローダウンが必要な場合はファイルを作成し、スローダウンを解消したい場合はファイルを削除します。(そして、各テスト間でそれを削除するクリーンアップコードがあります。)理論的には、ファイルよりも変数を使用することを好みますが、問題は、変数がリクエストごとに再初期化されることです。したがってlocation
、変数を設定して制限を無効にし、別の変数を無効にするブロックを持つことはできません。(これは私が最初に試したもので、変数の有効期間が原因で失敗しました)。Perl モジュールまたは Lua を使用して変数を保持したり、Cookie をいじったりすることはおそらく可能ですが、私はこれらのルートをたどらないことにしました。
重要事項:
echo
モジュールからのディレクティブ (echo_sleep
や などecho_exec
) を、応答を生成する nginx のストック ディレクティブと混合することはお勧めできません。私は最初にecho_sleep
一緒にいてproxy_pass
、悪い結果を得ました。そのため、株式ディレクティブをスタッフlocation /proxy/
から分離するブロックがあります。(ブロックを分割することで解決された同様の競合については、echo
この問題を参照してください。)
echo_exec
の内側と外側の 2 つのディレクティブは、if
仕組み上必要if
です。
このディレクティブは、クライアントがURLinternal
を直接要求するのを防ぎます。/proxy/...