2014-09-10 50 views
2

我nginx的以下配置承載我的形象服務:重寫查詢字符串路徑參數

upstream thumbor { 
     server localhost:8888; 
    } 

    server { 
     listen  80; 
     server_name my.imageserver.com; 
     client_max_body_size 10M; 
     rewrite_log on; 
     location ~ /images { 
      if ($arg_width="10"){ 
       rewrite ^/images(/.*)$ /unsafe/$1 last; 
      } 
      rewrite ^/images(/.*)$ /unsafe/$1 last; 
     } 
     location ~ /unsafe { 
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_set_header HOST $http_host; 
      proxy_set_header X-NginX-Proxy true; 

      proxy_pass http://thumbor; 
      proxy_redirect off; 
     } 

     location = /favicon.ico { 
      return 204; 
      access_log  off; 
      log_not_found off; 
     } 
    } 

我試圖改寫以下網址:從

http://my.imageserver.com/images/Jenesis/EmbeddedImage/image/jpeg/jpeg/9f5d124d-068d-43a4-92c0-1c044584c54a.jpeg

http://my.imageserver.com/unsafe/Jenesis/EmbeddedImage/image/jpeg/jpeg/9f5d124d-068d-43a4-92c0-1c044584c54a.jpeg

這是很容易的,問題開始時我想允許查詢字符串應該去URL的路徑,像這樣:

http://my.imageserver.com/images/Jenesis/EmbeddedImage/image/jpeg/jpeg/9f5d124d-068d-43a4-92c0-1c044584c54a.jpeg?width=150&height=200&mode=smart

http://my.imageserver.com/unsafe/150x200/smart/Jenesis/EmbeddedImage/image/jpeg/jpeg/9f5d124d-068d-43a4-92c0-1c044584c54a.jpeg

此外它會更好,如果查詢字符串的順序無關緊要。

我試過使用: $ arg_width但它似乎沒有工作。

在Ubuntu上使用nginx 1.6.1。

幫助將非常感激。

+0

請出示你現在所擁有的。我懷疑你沒有逃過問號,但很難看到你的錯誤在哪裏...... – Melvyn 2014-09-12 06:46:32

+0

這就是我目前的情況,我嘗試了幾種方法,包括$ arg_width,$ arg_height,但它沒有奏效。 – Afiku 2014-09-14 11:14:27

回答

4

處理查詢參數總是很難(對於Apache也是如此)。

但是當你做你的榜樣:

location ~ /images { 
    if ($arg_width="10"){ 
     rewrite ^/images(/.*)$ /unsafe/$1 last; 
    } 
    rewrite ^/images(/.*)$ /unsafe/$1 last; 
} 

我沒有看到2次重寫任何區別......所以這就是爲什麼,也許它不能正常工作。

反正你也許可以嘗試類似的東西(基於this thread):

location ^~ /images { 
    # get there only if we have a query string 
    if ($is_args) { 
     set $width ""; 
     set $height ""; 
     if ($args ~* "(?:^|&)width=([^&]+)") { 
      set $width $1; 
     } 
     if ($args ~* "(?:^|&)height=([^&]+)") { 
      set $height $1; 
     } 

     # string concatenation using sort of bash syntax 
     set $dim "${width}x${height}"; 
     # maybe we should add a control here on $dim !='x'... 

     # the ? here prevent query string from being appended 
     rewrite ^/images(/.*)$ /unsafe/$dim/$1? last; 
    } 
    rewrite ^/images(/.*)$ /unsafe/$1 last; 
} 
location ~ /unsafe { 
    (...) 
+0

它沒有工作,因爲顯然nginx不支持嵌套,如果但是當它嵌套它和改變一點它的工作邏輯偉大!謝謝您的幫助! – Afiku 2014-09-17 07:36:48

+0

是的,忘記了這個嵌套如果限制。作爲參考,您應該添加評論您的修補程序,或者編輯這個答案(或您的問題)的工作解決方案。也許可以將@Dayo的一部分作爲LUA腳本編寫,也是一種很好的避免nginx中的「if-Is-Evil」的方法,可以避免使用「if」進行危險操作。 – regilero 2014-09-17 17:29:11

+0

無法找到分割它的方法... – Afiku 2014-09-18 22:55:55

1

可以使用arg_name參數,你可以擺脫location塊:

rewrite ^/images/(.*)$ /unsafe/$1; 
# WARNING: Here we suppose that when we have a "mode" parameter, we have 
# width and height paremeters too 
if ($arg_mode) { 
    rewrite ^/unsafe/(.*)$ /images/unsafe/smart/$arg_mode/${arg_width}x${arg_height}/$1 last; 
} 
1

您需要作爲可以評估輸入並構建重寫URL的腳本選項。我使用第三方Nginx Lua Module這樣的邏輯。

在您的機器上安裝Lua或最好是LuaJit之後,您需要將模塊編譯爲Nginx。

或者,您可以安裝Openresty這是Nginx捆綁了幾個模塊,將Nginx完全轉換爲完整的Web應用程序服務器。在安裝過程中,Openresty將負責處理Lua/LuaJit依賴項。

如果你有這樣的地方,這應該爲你做的工作:

upstream thumbor { 
    server localhost:8888; 
} 
server { 
    [...] 
    location ~ ^/images { 
     rewrite_by_lua ' 
      -- Use local variables to limit their scope to this location block 
      local i, j, key, val, args, dimension, modetype, tempheight, replacement 

      -- We only go ahead if there are request arguments to start with 
      if ngx.var.is_args then 
       -- Get the request arguments 
       -- These are loaded into a Lua table of the form, { a = 1, b = 2, c = 3 } 
       args = ngx.req.get_uri_args() 
       -- Loop through the args table and build our replacement string 
       for key, val in pairs(args) do 
        if key == "width" then 
         if tempheight then 
          dimension = val .. "x" .. tempheight 
         else 
          dimension = val 
         end 
        elseif key == "height" then 
         if dimension then 
          dimension = dimension .. "x" .. val 
         else 
          tempheight = val 
         end 
        elseif key == "mode" then 
         modetype = val 
        end 
       end 

       -- Construct the replacement string. 
       replacement = "/unsafe/" .. dimension .. "/" .. modetype .. "/" 

       -- Replace "/images/" in the request url with the replacement string. 
       local newuri, n, err = ngx.re.sub(ngx.unescape_uri(ngx.var.request_uri), "/images/", replacement, "io") 

       -- If there is a new string, then redirect to the new URL 
       if newuri then 
        return ngx.redirect(newuri, 301) 
       end 
      end 
     '; 
    } 
    location ~ /unsafe { 
     [...] 
     proxy_pass http://thumbor; 
    } 
    [...] 
}