OpenResty笔记(二)

 2017-03-20 20:21:08     OpenResty  Nginx  Lua   1684


导读: OpenResty是Nginx与Lua的集合,掌握了Nginx和Lua,自然就掌握了OpenResty。

由于我对Lua比较陌生,所以,先从Lua开始,便于后续工作的开展。

获取URL参数

location /test {
   content_by_lua_block {
       local arg = ngx.req.get_uri_args()
       for k,v in pairs(arg) do
           ngx.say("[GET ] key:", k, " v:", v)
       end
   }
}

获取Body内容

location /test {
   content_by_lua_block {
       ngx.req.read_body()
       local arg = ngx.req.get_post_args()
       for k,v in pairs(arg) do
           ngx.say("[POST] key:", k, " v:", v)
       end
   }
}

或者

location /test {
   set body_data "";    
   content_by_lua_block {
       ngx.req.read_body()
       local data = ngx.req.get_body_data()
       ngx.var.body_data = data  --Lua变量赋值给Nginx变量
       ngx.say(data)
   }
}

#设置纯lua的外部模块搜索路径(';;' is the default path):

lua_package_path '/foo/bar/?.lua;/blah/?.lua;;';

#设置使用c编写的lua外部模块搜索路径(can also use ';;'):
lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;';

server {
    location /inline_concat {
        default_type 'text/plain';

        set $a "hello";
        set $b "world";
        # 嵌入lua脚本
        set_by_lua $res "return ngx.arg[1]..ngx.arg[2]" $a $b;
        echo $res;
    }

    location /rel_file_concat {
        set $a "foo";
        set $b "bar";
        # 脚本路径是nginx安装路径的相对路径
        # $ngx_prefix/conf/concat.lua 内容是:
        #
        #    return ngx.arg[1]..ngx.arg[2]
        #
        set_by_lua_file $res conf/concat.lua $a $b;
        echo $res;
    }

    location /abs_file_concat {
        set $a "fee";
        set $b "baz";
        # 使用绝对路径
        set_by_lua_file $res /usr/nginx/conf/concat.lua $a $b;
        echo $res;
    }

    location /lua_content {
        default_type 'text/plain';

        content_by_lua "ngx.say('Hello,world!')";
    }

     location /nginx_var {
        default_type 'text/plain';

        # 尝试请求 /nginx_var?a=hello,world 看看效果
        content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')";
    }

    location /request_body {
         # 读取request body (default off)
         lua_need_request_body on;
         client_max_body_size 50k;
         client_body_buffer_size 50k;

         content_by_lua 'ngx.print(ngx.var.request_body)';
    }

    # lua通过子请求来实现透明非阻塞的IO
    location /lua {
        default_type 'text/plain';

        content_by_lua '
            local res = ngx.location.capture("/some_other_location")
            if res.status == 200 then
                ngx.print(res.body)
            end';
    }

    # 发送一个GET /recur?num=5的请求,查看效果
    location /recur {
        default_type 'text/plain';

        content_by_lua '
           local num = tonumber(ngx.var.arg_num) or 0

           if num > 50 then
               ngx.say("num too big")
               return
           end

           ngx.say("num is: ", num)

           if num > 0 then
               res = ngx.location.capture("/recur?num=" .. tostring(num - 1))
               ngx.print("status=", res.status, " ")
               ngx.print("body=", res.body)
           else
               ngx.say("end")
           end
           ';
    }

    location /foo {
        rewrite_by_lua '
            res = ngx.location.capture("/memc",
                { args = { cmd = "incr", key = ngx.var.uri } }
            )
        ';

        proxy_pass http://blah.blah.com;
    }

    location /blah {
        access_by_lua '
            local res = ngx.location.capture("/auth")

            if res.status == ngx.HTTP_OK then
                return
            end

            if res.status == ngx.HTTP_FORBIDDEN then
                ngx.exit(res.status)
            end

            ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
        ';

        # proxy_pass/fastcgi_pass/postgres_pass/...
    }
    #调用lua脚本文件
    location /mixed {
        rewrite_by_lua_file /path/to/rewrite.lua;
        access_by_lua_file /path/to/access.lua;
        content_by_lua_file /path/to/content.lua;
    }

    # 在代码中使用nginx var
    # WARN: nginx var的内容必须仔细的过滤,
    # 否则会有很大的安全风险!
    location ~ ^/app/(.+) {
            content_by_lua_file /path/to/lua/app/root/$1.lua;
    }

    location / {
       lua_need_request_body on;

       client_max_body_size 100k;
       client_body_buffer_size 100k;

       access_by_lua '
           -- 查看客户端ip是否在我们的黑名单中
           if ngx.var.remote_addr == "132.5.72.3" then
               ngx.exit(ngx.HTTP_FORBIDDEN)
           end

           -- 查看请求body中是否有不和谐的词语
           if ngx.var.request_body and
                    string.match(ngx.var.request_body, "fsck")
           then
               return ngx.redirect("/terms_of_use.html")
           end

           -- tests passed
       ';

       # proxy_pass/fastcgi_pass/etc settings
    }
}

参考: