字符串(Literal strings) 以单引号或者双引号定界,同时可以包含以下C语言风格的转义字符:
\a --- 铃声(bell) \b --- 回退(backspace) \f --- form feed \n --- 新行(newline) \r --- 回车(carriage return) \t --- 水平制表符(horizontal tab) \v --- 垂直制表符(vertical tab) \\ --- 反斜杠(backslash) \" --- 双引号(quotation mark) \' --- 单引号(apostrophe)
\[ --- 左方括号(left square bracket)
\] --- 右方括号(right square bracket)
4.下面的表列出了Lua支持的所有字符类
. 任意字符
%a 字母
%c 控制字符
%d 数字
%l 小写字母
%p 标点字符
%s 空白符
%u 大写字母
%w 字母和数字
%x 十六进制数字
%z 代表0的字符
上面字符类的大写形式表示小写所代表的集合的补集。例如, '%A'非字母的字符:
模式串中的特殊字符
( ) . % + - * ? [ ^ $
'%' 用作特殊字符的转义字符
'%.' 匹配点;
'%%' 匹配字符 '%'。
转义字符 '%'不仅可以用来转义特殊字符,还可以用于所有的非字母的字符。当对一个字符有疑问的时候,为安全起见请使用转义字符转义他。
用'[]'创建字符集
'[%w_]' 匹配字母数字和下划线
'[01]' 匹配二进制数字
'[%[%]]'匹配一对方括号
在'[]'中使用连字符'-'
'%d' 表示 '[0-9]';
'%x' 表示 '[0-9a-fA-F]'
'[0-7]' 表示 '[01234567]'
在'[]'开始处使用 '^' 表示其补集:
'[^0-7]' 匹配任何不是八进制数字的字符;
'[^\n]' 匹配任何非换行符户的字符。
'[^%s]' == '%S'
模式修饰符
+ 匹配前一字符1次或多次
* 匹配前一字符0次或多次;最长匹配
- 匹配前一字符0次或多次;最短匹配
? 匹配前一字符0次或1次
^ 匹配字符串开头
$ 匹配字符串结尾
ngx_lua 模块提供的指令和API等:
指令名称
说明
lua_use_default_type
是否使用default_type指令定义的Content-Type默认值
lua_code_cache
*_by_lua_file文件是否cache
lua_regex_cache_max_entries
lua_regex_match_limit
lua_package_path
用Lua写的lua外部库路径(.lua文件)
lua_package_cpath
用C写的lua外部库路径(.so文件)
init_by_lua
master进程启动时挂载的lua代码
init_by_lua_file
init_worker_by_lua
worker进程启动时挂载的lua代码,常用来执行一些定时器任务
init_worker_by_lua_file
set_by_lua
设置变量
set_by_lua_file
content_by_lua
handler模块
content_by_lua_file
rewrite_by_lua
rewrite_by_lua_file
access_by_lua
access_by_lua_file
header_filter_by_lua
header filter模块
header_filter_by_lua_file
body_filter_by_lua
body filter模块,ngx.arg[1]代表输入的chunk,ngx.arg[2]代表当前chunk是否为last
body_filter_by_lua_file
log_by_lua
log_by_lua_file
lua_need_request_body
是否读请求体,跟ngx.req.read_body()函数作用类似
lua_shared_dict
创建全局共享的table(多个worker进程共享)
lua_socket_connect_timeout
TCP/unix 域socket对象connect方法的超时时间
lua_socket_send_timeout
TCP/unix 域socket对象send方法的超时时间
lua_socket_send_lowat
设置cosocket send buffer的low water值
lua_socket_read_timeout
TCP/unix 域socket对象receive方法的超时时间
lua_socket_buffer_size
cosocket读buffer大小
lua_socket_pool_size
cosocket连接池大小
lua_socket_keepalive_timeout
cosocket长连接超时时间
lua_socket_log_errors
是否打开cosocket错误日志
lua_ssl_ciphers
lua_ssl_crl
lua_ssl_protocols
lua_ssl_trusted_certificate
lua_ssl_verify_depth
lua_http10_buffering
rewrite_by_lua_no_postpone
lua_transform_underscores_in_response_headers
lua_check_client_abort
是否监视client提前关闭请求的事件,如果打开监视,会调用ngx.on_abort()注册的回调
lua_max_pending_timers
lua_max_running_timers
table
说明
ngx.arg
指令参数,如跟在content_by_lua_file后面的参数
ngx.var
变量,ngx.var.VARIABLE引用某个变量
ngx.ctx
请求的lua上下文
ngx.header
响应头,ngx.header.HEADER引用某个头
ngx.status
响应码
API
说明
ngx.log
输出到error.log
print
等价于 ngx.log(ngx.NOTICE, ...)
ngx.send_headers
发送响应头
ngx.headers_sent
响应头是否已发送
ngx.resp.get_headers
获取响应头
ngx.timer.at
注册定时器事件
ngx.is_subrequest
当前请求是否是子请求
ngx.location.capture
发布一个子请求
ngx.location.capture_multi
发布多个子请求
ngx.exec
ngx.redirect
ngx.print
输出响应
ngx.say
输出响应,自动添加'\n'
ngx.flush
刷新响应
ngx.exit
结束请求
ngx.eof
ngx.sleep
无阻塞的休眠(使用定时器实现)
ngx.get_phase
ngx.on_abort
注册client断开请求时的回调函数
ndk.set_var.DIRECTIVE
ngx.req.start_time
请求的开始时间
ngx.req.http_version
请求的HTTP版本号
ngx.req.raw_header
请求头(包括请求行)
ngx.req.get_method
请求方法
ngx.req.set_method
请求方法重载
ngx.req.set_uri
请求URL重写
ngx.req.set_uri_args
ngx.req.get_uri_args
获取请求参数
ngx.req.get_post_args
获取请求表单
ngx.req.get_headers
获取请求头
ngx.req.set_header
ngx.req.clear_header
ngx.req.read_body
读取请求体
ngx.req.discard_body
扔掉请求体
ngx.req.get_body_data
ngx.req.get_body_file
ngx.req.set_body_data
ngx.req.set_body_file
ngx.req.init_body
ngx.req.append_body
ngx.req.finish_body
ngx.req.socket
ngx.escape_uri
字符串的url编码
ngx.unescape_uri
字符串url解码
ngx.encode_args
将table编码为一个参数字符串
ngx.decode_args
将参数字符串编码为一个table
ngx.encode_base64
字符串的base64编码
ngx.decode_base64
字符串的base64解码
ngx.crc32_short
字符串的crs32_short哈希
ngx.crc32_long
字符串的crs32_long哈希
ngx.hmac_sha1
字符串的hmac_sha1哈希
ngx.md5
返回16进制MD5
ngx.md5_bin
返回2进制MD5
ngx.sha1_bin
返回2进制sha1哈希值
ngx.quote_sql_str
SQL语句转义
ngx.today
返回当前日期
ngx.time
返回UNIX时间戳
ngx.now
返回当前时间
ngx.update_time
刷新时间后再返回
ngx.localtime
ngx.utctime
ngx.cookie_time
返回的时间可用于cookie值
ngx.http_time
返回的时间可用于HTTP头
ngx.parse_http_time
解析HTTP头的时间
ngx.re.match
ngx.re.find
ngx.re.gmatch
ngx.re.sub
ngx.re.gsub
ngx.shared.DICT
ngx.shared.DICT.get
ngx.shared.DICT.get_stale
ngx.shared.DICT.set
ngx.shared.DICT.safe_set
ngx.shared.DICT.add
ngx.shared.DICT.safe_add
ngx.shared.DICT.replace
ngx.shared.DICT.delete
ngx.shared.DICT.incr
ngx.shared.DICT.flush_all
ngx.shared.DICT.flush_expired
ngx.shared.DICT.get_keys
ngx.socket.udp
udpsock:setpeername
udpsock:send
udpsock:receive
udpsock:close
udpsock:settimeout
ngx.socket.tcp
tcpsock:connect
tcpsock:sslhandshake
tcpsock:send
tcpsock:receive
tcpsock:receiveuntil
tcpsock:close
tcpsock:settimeout
tcpsock:setoption
tcpsock:setkeepalive
tcpsock:getreusedtimes
ngx.socket.connect
ngx.thread.spawn
ngx.thread.wait
ngx.thread.kill
coroutine.create
coroutine.resume
coroutine.yield
coroutine.wrap
coroutine.running
coroutine.status
ngx.config.debug
编译时是否有 --with-debug选项
ngx.config.prefix
编译时的 --prefix选项
ngx.config.nginx_version
返回nginx版本号
ngx.config.nginx_configure
返回编译时 ./configure的命令行选项
ngx.config.ngx_lua_version
返回ngx_lua模块版本号
ngx.worker.exiting
当前worker进程是否正在关闭(如reload、shutdown期间)
ngx.worker.pid
返回当前worker进程的pid
常量
说明
Core constants
ngx.OK (0)
ngx.ERROR (-1)
ngx.AGAIN (-2)
ngx.DONE (-4)
ngx.DECLINED (-5)
ngx.nil
HTTP method constants
ngx.HTTP_GET
ngx.HTTP_HEAD
ngx.HTTP_PUT
ngx.HTTP_POST
ngx.HTTP_DELETE
ngx.HTTP_OPTIONS
ngx.HTTP_MKCOL
ngx.HTTP_COPY
ngx.HTTP_MOVE
ngx.HTTP_PROPFIND
ngx.HTTP_PROPPATCH
ngx.HTTP_LOCK
ngx.HTTP_UNLOCK
ngx.HTTP_PATCH
ngx.HTTP_TRACE
HTTP status constants
ngx.HTTP_OK (200)
ngx.HTTP_CREATED (201)
ngx.HTTP_SPECIAL_RESPONSE (300)
ngx.HTTP_MOVED_PERMANENTLY (301)
ngx.HTTP_MOVED_TEMPORARILY (302)
ngx.HTTP_SEE_OTHER (303)
ngx.HTTP_NOT_MODIFIED (304)
ngx.HTTP_BAD_REQUEST (400)
ngx.HTTP_UNAUTHORIZED (401)
ngx.HTTP_FORBIDDEN (403)
ngx.HTTP_NOT_FOUND (404)
ngx.HTTP_NOT_ALLOWED (405)
ngx.HTTP_GONE (410)
ngx.HTTP_INTERNAL_SERVER_ERROR (500)
ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)
ngx.HTTP_SERVICE_UNAVAILABLE (503)
ngx.HTTP_GATEWAY_TIMEOUT (504)
Nginx log level constants
ngx.STDERR
ngx.EMERG
ngx.ALERT
ngx.CRIT
ngx.ERR
ngx.WARN
ngx.NOTICE
ngx.INFO
ngx.DEBUG
if res == ngx.null then
ngx.status = ngx.HTTP_NOT_FOUND
ngx.say("key not found.")
return ngx.status
end
ngx.say("result: ", res)
if res == ngx.null then
ngx.status = ngx.HTTP_NOT_FOUND
ngx.say("key not found.")
ngx.exit(ngx.status)
end
ngx.say("result: ", res)
location /original/url/to/remote {
lua_need_request_body on;
rewrite_by_lua '
--Lost of params but I only need 5 for the subrequest
local limited_post_args, err = ngx.req.get_post_args(5)
if not limited_post_args then
ngx.say("failed to get post args: ", err)
return
end
--setting limited number of params
ngx.req.set_body_data(ngx.encode_args(limited_post_args))
--rewriting url
local subreq_path = "/test"
ngx.req.set_uri(subreq_path)
';
proxy_pass http://echo.200please.com;
}
用lua脚本做nginx的访问的限制...
location @client{
proxy_pass http://www.ruifengyun.com;
}
location ~ /test {
default_type text/html;
content_by_lua 'ngx.say("this is ruifengyun.com!")';
access_by_lua '
if ngx.var.remote_addr == "10.2.20.110" then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
if ngx.var.remote_addr == "10.2.20.112" then
ngx.exec("@client")
end
';
}
控制经过判断之后,才能访问
location / {
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做nginx的rewrite跳转
这个是先判断 check-pam接口的return的内容是不是spam,是的话,转跳到其他的页面
location / {
rewrite_by_lua '
local res = ngx.location.capture("/check-spam")
if res.body == "spam" then
ngx.redirect("/terms-of-use.html")
end
'; fastcgi_pass ...;
}
根据ip做不同的响应
location / {
content_by_lua '
myIP = ngx.req.get_headers()["X-Real-IP"]
if myIP == nil then
myIP = ngx.req.get_headers()["x_forwarded_for"]
end
if myIP == nil then
myIP = ngx.var.remote_addr
end
if myIP == "" then
ngx.exec("@client")
else
ngx.exec("@client_test")
end
';
}
redirect的使用
return ngx.redirect("/foo")
return ngx.redirect("http://localhost:1984/foo", ngx.HTTP_MOVED_TEMPORARILY)
return ngx.redirect("/foo", 301)
返回302临时重定向 地址栏会显示跳转后的地址
rewrite ^ /foo? redirect; # nginx config
return ngx.redirect('/foo'); -- lua code
lua过滤post过来的参数
location = /test {
content_by_lua '
ngx.req.read_body()
local args = ngx.req.get_post_args()
for key, val in pairs(args) do
if type(val) == "table" then
ngx.say(key, ": ", table.concat(val, ", "))
else
ngx.say(key, ": ", val)
end
end
';
}
一个Lua的例子:
#!/usr/bin/env lua
ngx.say('aaaaaa </br>')
local url = ngx.var.uri
ngx.say('<br>',url,'<br/>')
ngx.print('这次访问的header头是 ',ngx.req.raw_header())
ngx.print('<meta http-equiv="content-type" content="text/html;charset=utf-8">')
ngx.print('<h1> 这个是 h1 </h1>')
ngx.print('这次访问的是 get 还是 post 呀 ',ngx.req.get_Method())
local args = ngx.req.get_uri_args()
ngx.print(args)
local res = ngx.location.capture("/")
ngx.print('<br>http code <br>‘,res.status)
lua 调用mysql的例子
worker_processes 2;
error_log logs/error.log warn;
events {
worker_connections 1024;
}
http {
upstream backend {
drizzle_server 127.0.0.1:3306 protocol=mysql
dbname=ngx_test user=ngx_test password=ngx_test;
drizzle_keepalive max=10 overflow=ignore mode=single;
}
server {
listen 8080;
location @cats-by-name {
set_unescape_uri $name $arg_name;
set_quote_sql_str $name;
drizzle_query 'select * from cats where name=$name';
drizzle_pass backend;
rds_json on;
}
location @cats-by-id {
set_quote_sql_str $id $arg_id;
drizzle_query 'select * from cats where id=$id';
drizzle_pass backend;
rds_json on;
}
location = /cats {
access_by_lua '
if ngx.var.arg_name then
return ngx.exec("@cats-by-name")
end
if ngx.var.arg_id then
return ngx.exec("@cats-by-id")
end
';
rds_json_ret 400 "expecting \"name\" or \"id\" query arguments";
}
}
}
改改密码就能用啦~
lua获取url中的参数
location = /adder {
set_by_lua $res "
local a = tonumber(ngx.arg[1])
local b = tonumber(ngx.arg[2])
return a + b" $arg_a $arg_b;
echo $res;
}
ngx.req.set_uri
nginx里面的配置是:
location /test {
rewrite ^/test/(.*) /$1 break;
proxy_pass http://my_backend;
}
lua里面的配置是:
location /test {
rewrite_by_lua '
local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "$1", "o")
ngx.req.set_uri(uri)
';
proxy_pass http://my_backend;
}