2011-10-25 50 views
7

我在匹配nginx $ request_body變量中的特定單詞時遇到問題。 我要代理通,如果身體請求中有一個特殊的詞,nginx匹配位置中的特定單詞

所以我的做法是這樣的:

location ~ \.php$ { 
if ($request_body ~* (.*)) {           
     proxy_pass http://test.proxy; 
      break; 
    } 

# other case... 
} 

此相匹配的一切,if語句作品, 但如果我改變了正則表達式無論如何,我無法得到一擊。

所以我現在的問題是:

如何我需要定義正確nginx的正則表達式來匹配,「目標」,例如?

在此先感謝!

+0

不要屏住呼吸。如果重要,您可以切換http://wiki.nginx.org/HttpCoreModule#client_body_in_single_buffer。但我不認爲你可以匹配請求正文 – rzab

+0

我現在明白,問題不在正則表達式中,但$ request_body在這一點上似乎是空的,我甚至嘗試了提供read_request_body方法的echo模塊,但是仍然是空的:( – sharpner

+0

確切地說,http://wiki.nginx.org/EmbeddedPerlModule doc提示$ nginx在內存中保存body與臨時文件中的body相反時,$ request_body是可用的。「有必要限制它的[ body size],並使用client_max_body_size爲緩衝區分配足夠的大小,「我想建議將client_max_body_size設置爲低於client_body_buffer_size的值, – rzab

回答

2

你的代碼有一些問題。

  1. 「($ request_body〜*(。*))」 從來沒有像別人等的 「其他情況」 表示匹配任何東西總是

  2. 更重要的是,它使用的結果「 proxy_pass「與」if「這是經典的邪惡。 http://wiki.nginx.org/IfIsEvil

爲了得到你想要的東西,使用第三方ngx_lua模塊(v0.3.1rc24及以上)...

location ~ \.php$ { 
    rewrite_by_lua ' 
     ngx.req.read_body() 
     local match = ngx.re.match(ngx.var.request_body, "target") 
     if match then 
      ngx.exec("@proxy"); 
     else 
      ngx.exec("@other_case");  
     end 
    '; 
} 

location @proxy {  
    # test.proxy stuff 
    ... 
} 

location @other_case { 
    # other_case stuff 
    ... 
} 

你可以在https://github.com/chaoslawful/lua-nginx-module/tags得到ngx_lua。

PS。請記住,lua的重寫總是在nginx重寫指令之後執行,所以如果你在其他情況下放置任何這樣的指令,它們將首先執行,你會得到一個funnies。

您應該將所有重寫寫入lua上下文中,以獲得一致的結果。這是「其他情況」的「if .. else .end」安排的原因。


您可能需要更長的這個版本


location ~ \.php$ { 
    rewrite_by_lua ' 
     --request body only available for POST requests 
     if ngx.var.request_method == "POST" 
      -- Try to read in request body 
      ngx.req.read_body() 
      -- Try to load request body data to a variable 
      local req_body = ngx.req.get_body_data() 
      if not req_body then 
       -- If empty, try to get buffered file name 
       local req_body_file_name = ngx.req.get_body_file() 
       --[[If the file had been buffered, open it, 
       read contents to our variable and close]] 
       if req_body_file_name then 
        file = io.open(req_body_file_name) 
        req_body = file:read("*a") 
        file:close() 
       end 
      end 
      -- If we got request body data, test for our text 
      if req_body then 
       local match = ngx.re.match(req_body, "target") 
       if match then 
        -- If we got a match, redirect to @proxy 
        ngx.exec("@proxy") 
       else 
        -- If no match, redirect to @other_case 
        ngx.exec("@other_case") 
       end 
      end 
     else 
      -- Pass non "POST" requests to @other_case 
      ngx.exec("@other_case") 
     end 
    '; 
} 
+0

我會盡力,儘管我寧願不使用lua這個:( – sharpner

+0

爲什麼不,如果我可能會問?在Nginx中的「IF」不是一個經典的編程條件語句,只是一個重寫屬性。這會引起很大的混淆,他會用不同的方式對它進行命名。在你的情況中,你需要經典的腳本條件語句,並且你必須使用腳本語言來實現這一點,這是沒有辦法的。基本上有兩個選擇:嵌入式Perl模塊或Lua模塊選擇你的毒藥:) – Dayo

+0

你可能是對的,我很想在沒有任何第三方模塊的情況下得到這種行爲;)但是我只是讀了一下,如果它和它realls是邪惡的:D感謝您的幫助......我現在看看perl xD – sharpner

0

Manual:

注:大括號({和}),因爲它們都在正則表達式 和用於塊控制中使用,以避免衝突,正則表達式與花括號 要與雙封閉報價(或單引號)。

所以儘量

if ($request_body ~* "(.*)") 

其他評論:代碼.*相匹配的一切。我會使用\w,因爲Perl正則表達式似乎可用。

你目前的if語句總是錯的,所以沒有命中是正確的輸出。