web-dev-qa-db-ja.com

要求メソッドがPOST、PUT、DELETEのいずれであるかに基づいたnginx proxy_pass

私は2つの iKaaro インスタンスをポート8080と9080で実行していますが、9080インスタンスは読み取り専用です。

たとえば、要求メソッドがPOST、PUT、DELETEの場合、nginxの使用方法がわからないので、書き込みインスタンス(8080)に送信し、それ以外は9080インスタンスに送信します。

正規表現を使用して場所を使用して何かを実行しましたが、これは正しくありません。

http://wiki.nginx.org/HttpLuaModule から呼び出すことができる「HTTPメソッド定数」があることがわかります。ロケーションブロックを次のように追加するのは正しいことです。

location ~* "(ngx.HTTP_POST|ngx.HTTP_DELETE|ngx.HTTP_PUT)" {
    proxy_pass http://127.0.0.1:8080;

ありがとう

22
khinester

私は簡単なテストをしました、そしてこれは私のためにうまくいきました:

server {
  location / {
    # This proxy_pass is used for requests that don't
    # match the limit_except
    proxy_pass http://127.0.0.1:8080;

    limit_except PUT POST DELETE {
      # For requests that *aren't* a PUT, POST, or DELETE,
      # pass to :9080
      proxy_pass http://127.0.0.1:9080;
    }
  }
}
36
kolbyjack

基本が整っていると思います。つまり、サーバーにLua 5.1またはそれ以上のLuaJIT 2.0をインストールし、ngx_luaモジュールを使用してNginxをコンパイルし、必要に応じてngx_luaを構成しました。

それが整ったら、これでうまくいきます:

location /test {
    content_by_lua '
        local reqType = ngx.var.request_method
        if reqType == ngx.HTTP_POST 
            OR reqType == ngx.HTTP_DELETE 
            OR reqType == ngx.HTTP_PUT 
        then
            res = ngx.location.capture("/write_instance")
        else
            res = ngx.location.capture("/read_instance")
        end
        ngx.say(res.body)
    ';
}
location /write_instance {
    internal;
    proxy_pass http://127.0.0.1:8080;
}
location /read_instance {
    internal;
    proxy_pass http://127.0.0.1:9080;
}

[〜#〜]更新[〜#〜]

おそらく、Luaをより広い範囲で使用していると思います。以下の例も、limit_exceptと同じ原理で機能します。

location /test {
    if ($request_method !~* GET) {
        # For Write Requests
        proxy_pass http://127.0.0.1:8080;
    }
    # For Read Requests
    proxy_pass http://127.0.0.1:9080;
}

「if」ブロックと「limit_except」ブロックの両方がネストされたロケーションブロックを効果的に作成し、条件が一致すると、作成された内部ロケーションブロックのコンテンツハンドラー(「proxy_pass」)のみが実行されます。

Ifが「悪」であると言われることがあるのは、これを完全に取得していないためですが、この場合、「if」と「limit_except」の両方に共通する「悪」の振る舞いが、まさにあなたが望むものになるかもしれません。

だからあなたが選ぶべき3つの選択肢!

ただし、他のディレクティブを設定する必要がある場合は、「if」オプションまたは「limit_except」オプションのいずれかを使用した「悪」な動作に噛まれないように注意する必要があります。

つまり、「if」または「limit_except」ブロック内にディレクティブを設定すると、そのディレクティブはその外部でアクティブにならず、同様に外部で設定されたものが内部で継承される可能性があります。したがって、両方のアプローチで、デフォルトが継承されるかどうか、場合によっては継承されないかどうかを監視する必要があります。

If is Evil ページにリストされているすべての潜在的な問題は、ここの「if」と「limit_except」に等しく適用されます。 Luaベースのスクリプトアプローチは、そのページで提案されているように、潜在的な落とし穴の多くを回避します。

幸運を!

11
Dayo

Nginxマップ機能をお勧めします。これはロケーションブロックの外に出ます:

map $request_method $destination {
    default 8080;
    PUT 9080;
    POST 9080;
    DELETE 9080;
}

次に、ロケーションブロックで:

proxy_pass http://127.0.0.1:$destination

これもすべて正規表現なので、次のようなことができます。

map $request_method $cookie_auth $destination {
    default 8080;
    "^POST " 9080;
    "^PUT someAuthCookieValue" 9080;
}

さらに、これによりifの使用がまったく回避されます。それはかなり素晴らしいです。これを使用して、WordPressクラスター内のすべての書き込みトラフィックをリモートノード上の1つのFastCGI TCPソケットに転送しますが、読み取りトラフィックをローカルのFastCGI UNIXソケットに送信します。

1
Andrea Rutledge

リクエストメソッドで単純に条件を作成する方法を探している人の場合、構文は次のとおりです。

if ($request_method = DELETE ) {
   . . . 
}
1
Sych