魏长东

weichangdong

lua学习-进阶篇

set_by_lua 

设置nginx变量,我们用的set指令即使配合if指令也很难实现负责的赋值逻辑;

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}
 

http {
    include       mime.types;
    default_type  application/octet-stream;

    lua_package_path "lualib/?.lua;;";  #lua 模块  
    lua_package_cpath "lualib/?.so;;";  #c模块
    lua_shared_dict shared_data 1m; 
    init_by_lua_file html/init.lua; 
    #init_worker_by_lua_file html/init_work.lua; 
	lua_code_cache off;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

	map $host $wcd 
	{  
		default                     "0";  
		www.wcd.com            "wcd"; 
		www.yy.com	"yy";
	}

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location /hello {
            default_type 'text/html';  
	    
	    content_by_lua 'ngx.say("hello world")';
        }

	location /test1 {
            default_type 'text/html';  
	    
	content_by_lua_file  html/test1.lua;
        }
	location ~ /test2/(\d+)/(\d+) { 
	
	    #设置nginx变量  
	    set $a $1;   
	    set $b $host;  
	    default_type "text/html";  
	    #nginx内容处理  
	    content_by_lua_file html/test2.lua;  
	    #内容体处理完成后调用  
	    echo_after_body "ngx.var.b $b";  
	} 
	location /test3{
		
		default_type "text/html";  
		content_by_lua_file html/test3.lua; 
	}

	location /test4{
		
		default_type "text/html";  
		content_by_lua_file html/test4.lua; 
	}
	location /test5{
		
		default_type "text/html";  
		content_by_lua_file html/test5.lua; 
	}
	location /test6{
	
		default_type "text/html";  
		content_by_lua_file html/test6.lua; 
	}
	location /test7{
		default_type "text/html";  
		content_by_lua_file html/test7.lua; 
	}

	location /test8{
		default_type "text/html";  
		set_by_lua_file $num html/test8.lua;  
		 content_by_lua_file html/test8_1.lua;  
	}
	location /test9{
		default_type "text/html";  
		echo 'wcd';  
	}

	location /test10{
		default_type "text/html";  
		rewrite_by_lua_file html/test10.lua;  
		echo 'wcd';  
	}


        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

    server {
        listen       80;
        server_name  www.wcd.com;

        #charset koi8-r;
	location /{
		default_type "text/html";  
		rewrite_by_lua_file html/test10.lua;  
	}
        #access_log  logs/host.access.log  main;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

set_by_lua_file:语法set_by_lua_file $var lua_file arg1 arg2...; 在lua代码中可以实现所有复杂的逻辑,但是要执行速度很快,不要阻塞;

test8.lua 文件代码

local uri_args = ngx.req.get_uri_args()  
local i = uri_args["i"] or 0  
local j = uri_args["j"] or 0  
return i + j;

得到请求参数进行相加然后返回。

访问 http://localhost/test8?i=12&j=23

输出 35

访问 localhost/test9【nginx 居然可以使用php 的echo 之前想调试nginx的某个参数,不知道从何下手,这个方法好啊 】

输出 wcd

 

test10.lua代码

ngx.say(ngx.var.wcd);

访问 localhost/test10 【主要是想调试下 nginx用map 来设置变量】

输出 0 【map 有个default 的数值是 0】

访问www.wcd.com 【host配置指向127.0.0.1】

输出 wcd 【因为此时$host 是www.wcd.com,map 变量的 数值是wcd】

rewrite_by_lua 

执行内部URL重写或者外部重定向,典型的如伪静态化的URL重写。其默认执行在rewrite处理阶段的最后。

location /test11{
		default_type "text/html";  
		rewrite_by_lua_file html/test11.lua;  
		echo "rewrite uri : $uri, a : $arg_a"; 
	}

	
	location /test12{
		default_type "text/html";  
		rewrite_by_lua_file html/test12.lua;  
		echo "rewrite uri : $uri, a : $arg_a"; 
	}

test11.lua 代码

if ngx.req.get_uri_args()["jump"] == "1" then  
   ngx.req.set_uri("/lua_rewrite_3", false);  
   ngx.req.set_uri("/lua_rewrite_4", false);  
   ngx.req.set_uri_args({a = 1, b = 2});  
end  

访问 http://localhost/test11 输出

rewrite uri : /test11, a :

访问 http://localhost/test11?jump=1 输出

rewrite uri : /lua_rewrite_4, a : 1

然后以上两个都没有进行实质的跳转。

下面就让他真正的跳转。

代码test12.lua 代码

if ngx.req.get_uri_args()["jump"] == "1" then  
ngx.log(ngx.ERR, "=====yes====\n");
   ngx.req.set_uri("/test1", true);   
    ngx.log(ngx.ERR, "=====no====\n");
   ngx.req.set_uri_args({a = 111, b = 222});  
end  

通过访问 http://localhost/test12?jump=1

输出是我的第一个例子的输出

im ngx print 
im ngx say

虽然跳转了,但是浏览器网页还是显示的test12的,而不是test1的。

而且看日志,输出了跳转前的,之后的log都没有了。

2016/04/10 14:30:24 [error] 4900#5352: *1 [lua] test12.lua:2: =====yes====
, client: 127.0.0.1, server: localhost, request: "GET /test12?jump=1 HTTP/1.1", host: "localhost"

ngx.req.set_uri(uri, false):可以内部重写uri(可以带参数),等价于 rewrite ^ /test11;通过配合if/else可以实现 rewrite ^ /test11;这种功能;此处两者都是location内部url重写,不会重新发起新的location匹配;

ngx.req.set_uri_args:重写请求参数,可以是字符串(a=1&b=2)也可以是table;

 

ngx.req.set_uri(uri, true):可以内部重写uri,即会发起新的匹配location请求,等价于 rewrite ^ /lua_rewrite_4 last;此处看error log是看不到我们记录的log。

 

注意,在使用rewrite_by_lua时,开启rewrite_log on;后也看不到相应的rewrite log。

access_by_lua 

用于访问控制,比如我们只允许内网ip访问,可以使用如下形式

allow     127.0.0.1;  
allow     10.0.0.0/8;  
allow     192.168.0.0/16;  
allow     172.16.0.0/12;  
deny      all;  

配置nginx 

location /test13{
		default_type "text/html";  
		access_by_lua_file html/test13.lua;  
		echo "access"; 
	}

test13.lua 代码

if ngx.req.get_uri_args()["token"] ~= "wcd" then  
   return ngx.exit(403)  
end  

访问 http://localhost/test13  页面出现 403

访问 http://localhost/test13?token=wcd 

输出 access。

发现lua配合nginx,真是好强大啊。