2014-09-10 52 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; 
    } 
    [...] 
}