2016-04-30 61 views
1

我有一個應用程序運行在nginx後面。爲了讓客戶添加相同主機根據自己的工具,我們使用location排序是這樣的:如何在nginx中創建自定義位置?

location /some-extension { 
    rewrite ^/(.*) /$1 break; 
    proxy_pass http://customers-app/$1/$args; 
} 

現在,我想使這個充滿活力,從而使得給用戶可以創建零個或多個這樣的位置。由於該應用程序是通過Docker部署的,因此無法手動編輯nginx配置。

Nginx的編譯使用Perl和Lua支持,所以我想是這樣的:

  • 使用環境現狀變量的形式path1 url1 path-2 url2 ... pathn urln上配置外部工具。
  • 在特殊的location配置中,將請求URL的第一個路徑段與環境變量匹配,並將proxy_pass與相應的URL匹配(如果找到)。

到目前爲止,這是我所:

location/{ 
    content_by_lua ' 
     local target_path = ngx.var.uri; 
     local name = nil 

     if target_path:len() > 0 then 
     startAt = target_path:find("/") + 1 
     endAt = target_path:find("/", startAt) - 1 
     name = target_path:sub(startAt,endAt) 
     ngx.say(name) 
     end 

     if name then 
     local custom_proxies = os.getenv("CUSTOM_PROXIES"); 
     inString = custom_proxies:find("another ") 
     if not inString then 
      ngx.say("not in string") 
     else 
      startAt = custom_proxies:find(" ", inString + 1) + 1 
      endAt = custom_proxies:find(" ", startAt) 

      url = custom_proxies:sub(startAt,endAt) 
      ngx.say(url) 

     end 
     end 

    '; 
    } 

我知道我不應該使用content_by_lua但似乎排序工作。問題是我怎麼能得到這個proxy_pass到指定的網址?

回答

0

我解決它通過以下方式:

  • 環境變量應該是名稱和URL的空格分隔列表; key http://example.com/app1 key2 http://acme.com

  • 一個Lua腳本讀取環境變量爲table,其中key爲關鍵字,下面的URL爲值。

  • nginx location塊將處理請求並使用Lua腳本查找要代理的模塊。

  • 函數將接受請求路徑並從中找到關鍵字,然後查找表中的URL。

這裏的腳本:

local custom_proxies = os.getenv("CUSTOM_PROXIES") 
local custom_modules = {} 

local cutFrom = 0 
local cutTo = 0 

while cutTo < custom_proxies:len() do 
    cutFrom = cutTo 
    cutTo = custom_proxies:find(" ", cutFrom + 1) 
    local name = custom_proxies:sub(cutFrom, cutTo - 1) 
    cutFrom = cutTo + 1 
    cutTo = custom_proxies:find(" ", cutFrom) 

    if not cutTo then 
    cutTo = custom_proxies:len() + 1 
    end 

    local url = custom_proxies:sub(cutFrom, cutTo - 1) 
    custom_modules[name] = url 
    cutTo = cutTo + 1 
end 

function custom_modules.get_url(target_path) 
    local name = nil 

    local startAt = target_path:find("/", 6) + 1 
    local endAt = target_path:find("/", startAt) 
    if not endAt then 
    endAt = target_path:len() 
    else 
    endAt = endAt - 1 
    end 
    name = target_path:sub(startAt,endAt) 
    if name then 
    return custom_modules[name] 
    else 
    ngx.log(ngx.STDERR, "Not able to deduct module name from URI") 
    return "" 
    end 
end 

return custom_modules 

這裏的nginx的location

location /custom/ { 
    set_by_lua $redirect_to ' 
    local custom_modules = require "read_proxies" 
    local url = custom_modules.get_url(ngx.var.uri) 

    if not url then 
     ngx.log(ngx.STDERR, "Not a known custom module.") 
    end 
    return url 
    '; 

    if ($redirect_to = '') { 
    return 404 'Unknown custom module.'; 
    } 

    rewrite ^/custom/\w+/(.*) /$1 break; 
    proxy_pass $redirect_to$1?$args; 

} 

的想法是,請求諸如/custom/foobar/path/to/something?page=2將使用foobar作爲重點來查找網址和proxy_pass與其餘的路徑和參數。

相關問題