如何使用MySQL在Nginx上使用动态doc root?

时间:2014-09-21 04:39:22

标签: mysql nginx lua openresty

我一直试图找到一种方法来首先捕获环境变量HOSTNAME,然后使用MySQL查询获取并返回Nginx conf我们的vhosts的文档根目录。我们将它们用于当前在Apache中的动态doc根,但是正在迁移到Nginx。

示例nginx.conf(可能看起来像这样):

server {
    listen   80;
     # grab Environment variable HOSTNAME
     $hostname= ENV(HOSTNAME);
     # execute mysql query
    $doc_root = mysql(select docroot from table where host = '$hostname' );
     # set document root
    root           /var/www/$doc_root;

..... 我正在使用Lua和https://github.com/openresty/lua-resty-mysql进行探索,但一直无法弄清楚如何将HOSTNAME和mysql查询捕获为变量并返回结果。

2 个答案:

答案 0 :(得分:1)

感谢您的帮助。它对我没有用,但经过大量的工作,我终于有了一些工作。如果他们需要,这是给其他人的

事实证明$ http_host已经在nginx中全局定义 - 所以这是固定的。

        set $httphost $http_host; # create and initialize var
        set $docroot "";

    # begin LUA scripting
    rewrite_by_lua '
                    -- make sure http host is defined
                    if not ngx.var.httphost then
                      ngx.log(ngx.ERR,"ERROR - no httphost defined")
                      return
                    end

                       -- begin mysql
                    local mysql = require "resty.mysql"
                    local db, err = mysql:new()

                    db:set_timeout(1000) -- 1 sec

                    local ok, err, errno, sqlstate = db:connect
                    {
                            host = "127.0.0.1",
                            port = 3306,
                            database = "db",
                            user = "user",
                            password = "password",
                            max_packet_size = 1024 * 1024
                    }

                    if not ok then
                      ngx.log(ngx.ERR,"MySQL failed to connect: ", err, ": ", errno, " ", sqlstate)
                      return
                    end

                    -- prevent injection attack
                    local hname = ngx.unescape_uri(client)
                    local quoted_name = ngx.quote_sql_str(hname)

                    local sql = "select docroot from users where customer =" .. quoted_name
                    result,err,errno,sqlstate = db:query(sql,1)
                    if not result then
                       ngx.log(ngx.ERR,"MySQL bad result: ", err, ": ", errno, ": ", sqlstate, ".")
                       return
                    end

                    if not result[1].docroot then
                      ngx.log(ngx.ERR,"MySQL ERROR - no docroot was returned")
                      return
                    end

                    ngx.var.docroot = result[1].docroot
            ';
           # now we can set the docroot for this host
          root           /var/www/$docroot;

答案 1 :(得分:0)

首先,使用数据库进行基本路由听起来不是一个好主意 - 我建议将结果缓存在内存中,并可能定期从数据库中刷新它们。

其次,基本的Nginx配置文件只会到目前为止 - 为了获得更高级的功能,您需要在它上面使用脚本语言(如Lua)。这允许您阅读环境变量之一。我在这里写了如何做到这一点:

https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html

让Lua使用Nginx的常用方法是使用Openresty,这是Nginx的一个版本,它预装了几个模块,包括Lua。您可以将lua-resty-mysql添加到混音中,然后直接从Lua执行您想要的所有操作。我从来没有使用过lua-resty-mysql所以我无法为你编写代码。如果你开始使用Mysql,你将不得不研究它的文档。看看Redis,你可能比Mysql更适合。