2011-12-21 93 views
19

我有兩個iKaaro實例在端口8080和9080上運行,其中9080實例是隻讀的。nginx proxy_pass基於請求方法是POST,PUT還是DELETE

我不確定如何使用nginx例如,如果請求方法是POST,PUT,DELETE然後發送到寫實例(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; 

感謝

+0

你能解釋一下這個問題好一點?你嘗試過這種設置嗎?你有任何錯誤(哪些)? – kikito 2011-12-21 16:22:46

回答

33

我只是做了一個快速測試,而這個工作對我來說:

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

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

這是更短 – khinester 2011-12-21 20:22:55

+1

它也不會依賴於任何第三方模塊 – kolbyjack 2011-12-21 20:37:48

+2

不爲我上的nginx 1.7.6 .. – 2015-01-31 16:36:38

10

我假設你得到了基礎知識到位。 I.E.,您已經在您的服務器上安裝了Lua 5.1或更好的LuaJIT 2.0,編譯了Nginx和ngx_lua模塊,並根據需要配置了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; 
} 

UPDATE

我想也許你是專門在更大範圍內使用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」和「limit_except」共同的「邪惡」行爲可能正是你想要的。

因此有三種選擇供您挑選!

但是請注意,如果您需要設置任何其他指令,您將不得不注意「if」或「limit_except」選項中的「邪惡」行爲。如果您在「if」或「limit_except」塊內設置了一個指令,它可能不在其外部,並且類似地,外部設置的內容可能會被繼承。所以你必須看兩種方法如何默認繼承,或者不是,視情況而定。

If is Evil頁面上列出的所有潛在問題均適用於此處的「if」和「limit_except」。基於Lua的腳本編寫方法將避免該頁面上提出的許多潛在缺陷。

祝你好運!

+0

謝謝你這是有道理的。 – khinester 2011-12-21 20:20:32

+0

感謝您的詳細解釋,所以我需要注意IfiSEvil是否需要運行其他指令。 我可能需要我還需要包括特定的URL,例如位置〜*「(登錄| NEW_CONTENT)」 {...但我會揣摩出來,回到這裏與我的nginx.conf文件,看看是否它可以得到改善。 – khinester 2011-12-22 11:01:08

+0

嘗試按特定問題分開查詢。我假設在你有三個選項的情況下,關於如何基於請求方法的Nginx路由請求的具體問題已經得到了詳盡的解答。你可以直接使用「if」,也可以使用「limit_except」這個if語句來記住潛在的問題,或者使用腳本方法,比如給出的Lua例子來避免這些問題。您可能需要考慮接受給出的答案中的一個或另一個,並詢問是否存在其他問題。 – Dayo 2011-12-22 13:28:36

1

萬一有人找一種方式來簡單地使被請求方法的條件下,語法是:

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

..although工作,我不得不提,那使用IF在配置不推薦nginx團隊:http://wiki.nginx.org/IfIsEvil – Sych 2015-02-04 20:02:53

1

我會推薦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; 
} 

加上這完全避免使用。這非常棒。我用它將一個WordPress集羣中的所有寫入流量定向到遠程節點上的一個FastCGI TCP套接字,但將讀取的流量發送到本地FastCGI UNIX套接字。

相關問題