【问题标题】:How can I make custom locations in nginx?如何在 nginx 中创建自定义位置?
【发布时间】:2016-08-25 11:24:04
【问题描述】:

我有一个在 nginx 后面运行的应用程序。为了允许客户在相同的主机名下添加他们自己的工具,我们使用 location 类似这样:

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到指定的URL?

【问题讨论】:

    标签: http nginx lua


    【解决方案1】:

    我通过以下方式解决了它:

    • 环境变量应该是空格分隔的名称和 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 作为键来查找URL,并使用proxy_pass 与其余路径和参数一起查找它。

    【讨论】:

      猜你喜欢
      • 2016-06-05
      • 1970-01-01
      • 2015-07-28
      • 2020-06-05
      • 1970-01-01
      • 2016-03-12
      • 2011-11-21
      • 2017-11-22
      • 1970-01-01
      相关资源
      最近更新 更多