## 使用摘要
```nginx
# 设置纯 Lua 扩展库的搜寻路径(';;' 是默认路径):
lua_package_path '/foo/bar/?.lua;/blah/?.lua;;';
# 设置 C 编写的 Lua 扩展模块的搜寻路径(也可以用 ';;'):
lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;';
server {
location /inline_concat {
# default_type 指令设置默认 MIME 类型:
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 prefix 的相对路径
# 文件 $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 设置默认的 MIME 类型:
default_type 'text/plain';
content_by_lua "ngx.say('Hello,world!')";
}
location /nginx_var {
# 通过 default_type 设置默认的 MIME 类型:
default_type 'text/plain';
# 试试访问 /nginx_var?a=hello,world
content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')";
}
location /request_body {
# 强制读取请求 body (默认是关)
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 非阻塞 I/O 调用
location /lua {
# 通过 default_type 设置默认的 MIME 类型:
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 设置默认的 MIME 类型:
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/...
}
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 变量
# 注意: NGINX 变量的内容一定要做仔细的过滤,否则会有很大的安全风险
location ~ ^/app/([-_a-zA-Z0-9/]+) {
set $path $1;
content_by_lua_file /path/to/lua/app/root/$path.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
}
}
```
> English Version
```nginx
# set search paths for pure Lua external libraries (';;' is the default path):
lua_package_path '/foo/bar/?.lua;/blah/?.lua;;';
# set search paths for Lua external libraries written in C (can also use ';;'):
lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;';
server {
location /inline_concat {
# MIME type determined by default_type:
default_type 'text/plain';
set $a "hello";
set $b "world";
# inline Lua script
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";
# script path relative to nginx prefix
# $ngx_prefix/conf/concat.lua contents:
#
# 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";
# absolute script path not modified
set_by_lua_file $res /usr/nginx/conf/concat.lua $a $b;
echo $res;
}
location /lua_content {
# MIME type determined by default_type:
default_type 'text/plain';
content_by_lua "ngx.say('Hello,world!')";
}
location /nginx_var {
# MIME type determined by default_type:
default_type 'text/plain';
# try access /nginx_var?a=hello,world
content_by_lua "ngx.print(ngx.var['arg_a'], '\\n')";
}
location /request_body {
# force reading 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)';
}
# transparent non-blocking I/O in Lua via subrequests
location /lua {
# MIME type determined by default_type:
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 {
# MIME type determined by default_type:
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/...
}
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;
}
# use nginx var in code path
# WARNING: contents in nginx var must be carefully filtered,
# otherwise there'll be great security risk!
location ~ ^/app/([-_a-zA-Z0-9/]+) {
set $path $1;
content_by_lua_file /path/to/lua/app/root/$path.lua;
}
location / {
lua_need_request_body on;
client_max_body_size 100k;
client_body_buffer_size 100k;
access_by_lua '
-- check the client IP address is in our black list
if ngx.var.remote_addr == "132.5.72.3" then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- check if the request body contains bad words
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
}
}
```
- Name yuansheng-8.4 WenMing(√)
- Status yuansheng-8.6 WenMing(√)
- Version
- Synopsis yuansheng-8.6 WenMing(√)
- Description yuansheng-8.16 WenMing(√)
- Typical Uses yuansheng-8.16 WenMing(√)
- Nginx Compatibility yuansheng-8.17 WenMing(√)
- Installation yuansheng-8.17 WenMing(√)
- C Macro Configurations yuansheng-8.17 WenMing(√)
- Installation on Ubuntu 11.10 yuansheng-8.18
- Community
- English Mailing List
- Chinese Mailing List
- Code Repository yuansheng-8.20 WenMing(√)
- Bugs and Patches yuansheng-8.20 WenMing(√)
- Lua/LuaJIT bytecode support yuansheng-8.31
- System Environment Variable Support yuansheng-9.1
- HTTP 1.0 support lance-2015.8.13
- Statically Linking Pure Lua Modules yuansheng-9.1
- Nginx Worker内的数据共享 lance-2015.8.5
- Known Issues
- TCP socket connect operation issues yuansheng-9.2
- Lua Coroutine Yielding/Resuming yuansheng-9.2
- Lua Variable Scope yuansheng-9.2
- Locations Configured by Subrequest Directives of Other Modules lance-2015.8.12
- Cosockets Not Available Everywhere yuansheng-9.2
- 特别转义序列 lance-2015.8.5
- Mixing with SSI Not Supported yuansheng-9.2
- SPDY Mode Not Fully Supported yuansheng-9.2
- Missing data on short circuited requests yuansheng-9.2
- TODO yuansheng-9.3
- Changes yuansheng-9.3 WenMing(√)
- Test Suite yuansheng-9.3
- Copyright and License yuansheng-9.3
- See Also yuansheng-9.3
- Directives yuansheng-9.3
- Nginx API for Lua yuansheng-9.3
- Obsolete Sections yuansheng-9.3
- lua_use_default_type hambut 2015.8.5
- lua_code_cache hambut 2015.8.5
- lua_regex_cache_max_entries yuansheng-9.3
- lua_regex_match_limit yuansheng-9.3
- lua_package_path yuansheng-9.4
- lua_package_cpath yuansheng-9.4
- init_by_lua yuansheng-9.4
- init_by_lua_file yuansheng-9.4
- init_worker_by_lua yuansheng-9.6
- init_worker_by_lua_file yuansheng-9.6
- set_by_lua yuansheng-9.6
- set_by_lua_file yuansheng-9.6
- content_by_lua dengshiyong 2015.8.12 WenMing(√)
- content_by_lua_file yuansheng-9.19
- rewrite_by_lua yuansheng-9.19
- rewrite_by_lua_file yuansheng-9.19
- access_by_lua yuansheng-9.27
- access_by_lua_file yuansheng-9.28
- header_filter_by_lua liujinxuan 2015.9.1
- header_filter_by_lua_file yuansheng-9.28
- body_filter_by_lua yuansheng-9.28
- body_filter_by_lua_file yuansheng-9.28
- log_by_lua yuansheng-9.28
- log_by_lua_file yuansheng-9.28
- lua_need_request_body yuansheng-9.28
- lua_shared_dict lance-2015.8.20
- lua_socket_connect_timeout yuansheng-9.28
- lua_socket_send_timeout yuansheng-9.28
- lua_socket_send_lowat yuansheng-9.28
- lua_socket_read_timeout yuansheng-9.28
- lua_socket_buffer_size yuansheng-9.28
- lua_socket_pool_size yuansheng-9.28
- lua_socket_keepalive_timeout yuansheng-9.28
- lua_socket_log_errors yuansheng-9.28
- lua_ssl_ciphers yuansheng-9.29
- lua_ssl_crl yuansheng-9.29
- lua_ssl_protocols yuansheng-9.29
- lua_ssl_trusted_certificate yuansheng-9.29
- lua_ssl_verify_depth yuansheng-9.29
- lua_http10_buffering yuansheng-9.29
- rewrite_by_lua_no_postpone yuansheng-9.29
- lua_transform_underscores_in_response_headers yuansheng-9.29
- lua_check_client_abort yuansheng-9.29
- lua_max_pending_timers yuansheng-9.29
- lua_max_running_timers yuansheng-9.29
- ngx.arg lance-2015.8.19
- ngx.var.VARIABLE lance-2015.8.19
- Core constants lance-2015.8.14 WenMing(√)
- HTTP method constants lance-2015.8.13
- HTTP status constants lance-2015.8.13
- Nginx log level constants lance-2015.8.13
- print lance-2015.8.14
- ngx.ctx lance-2015.8.14
- ngx.location.capture lance-2015.8.11
- ngx.location.capture_multi lance-2015.8.11
- ngx.status lance-2015.8.18 yuansheng(√)
- ngx.header.HEADER lance-2015.9.6 yuansheng(√)
- ngx.resp.get_headers lance-2015.9.7 yuansheng(√)
- ngx.req.start_time lance-2015.9.9 yuansheng(√)
- ngx.req.http_version lance-2015.9.9 yuansheng(√)
- ngx.req.raw_header lance-2015.9.9 yuansheng(√)
- ngx.req.get_method lance-2015.9.9 yuansheng(√)
- ngx.req.set_method lance-2015.9.9 yuansheng(√)
- ngx.req.set_uri lance-2015.9.9
- ngx.req.set_uri_args lance-2015.9.10
- ngx.req.get_uri_args lance-2015.9.10
- ngx.req.get_post_args lance-2015.9.10
- ngx.req.get_headers lance-2015.9.11
- ngx.req.set_header lance-2015.9.14
- ngx.req.clear_header lance-2015.9.14
- ngx.req.read_body lance-2015.9.16
- ngx.req.discard_body lance-2015.9.24
- ngx.req.get_body_data lance-2015.9.24
- ngx.req.get_body_file lance-2015.9.28
- ngx.req.set_body_data lance-2015.9.28
- ngx.req.set_body_file lance-2015.9.28
- ngx.req.init_body lance-2015.9.28
- ngx.req.append_body lance-2015.9.28
- ngx.req.finish_body lance-2015.9.28
- ngx.req.socket yuansheng-10.12
- ngx.exec yuansheng-10.12
- ngx.redirect yuansheng-10.12
- ngx.send_headers yuansheng-10.12
- ngx.headers_sent yuansheng-10.12
- ngx.print lance-2015.8.7
- ngx.say lance-2015.8.7
- ngx.log lance-2015.8.13
- ngx.flush lance-2015.8.13
- ngx.exit lance-2015.8.13
- ngx.eof lance-2015.8.18
- ngx.sleep lance-2015.8.18
- ngx.escape_uri lance-2015.8.18
- ngx.unescape_uri lance-2015.8.18
- ngx.encode_args lance-2015.8.18
- ngx.decode_args lance-2015.8.18
- ngx.encode_base64 hambut-2015.9.9
- ngx.decode_base64 hambut-2015.9.9
- ngx.crc32_short hambut-2015.9.9
- ngx.crc32_long hambut-2015.9.9
- ngx.hmac_sha1 hambut-2015.9.9
- ngx.md5 hambut-2015.9.9
- ngx.md5_bin hambut-2015.9.9
- ngx.sha1_bin hambut-2015.9.9
- ngx.quote_sql_str hambut-2015.9.9
- ngx.today bells-2015.8.8
- ngx.time bells-2015.8.22
- ngx.now bells-2015.8.22
- ngx.update_time bells-2015.8.16
- ngx.localtime bells-2015.8.22
- ngx.utctime bells-2015.8.22
- ngx.cookie_time yuansheng-10.12
- ngx.http_time yuansheng-10.10
- ngx.parse_http_time yuansheng-10.10
- ngx.is_subrequest yuansheng-10.8
- ngx.re.match lance-2015.8.6
- ngx.re.find lance-2015.8.6
- ngx.re.gmatch lance-2015.8.6
- ngx.re.sub lance-2015.8.6
- ngx.re.gsub lance-2015.8.6
- ngx.shared.DICT lance-2015.8.10
- ngx.shared.DICT.get lance-2015.8.10
- ngx.shared.DICT.get_stale lance-2015.8.10
- ngx.shared.DICT.set lance-2015.8.10
- ngx.shared.DICT.safe_set lance-2015.8.10
- ngx.shared.DICT.add lance-2015.8.10
- ngx.shared.DICT.safe_add lance-2015.8.10
- ngx.shared.DICT.replace lance-2015.8.10
- ngx.shared.DICT.delete lance-2015.8.10
- ngx.shared.DICT.incr lance-2015.8.10
- ngx.shared.DICT.flush_all lance-2015.8.10
- ngx.shared.DICT.flush_expired lance-2015.8.10
- ngx.shared.DICT.get_keys lance-2015.8.10
- ngx.socket.udp yuansheng-10.8
- udpsock:setpeername yuansheng-10.8
- udpsock:send yuansheng-10.8
- udpsock:receive yuansheng-10.8
- udpsock:close yuansheng-10.8
- udpsock:settimeout yuansheng-10.8
- ngx.socket.tcp yuansheng-10.7
- tcpsock:connect yuansheng-10.7
- tcpsock:sslhandshake yuansheng-10.7
- tcpsock:send yuansheng-10.7
- tcpsock:receive yuansheng-10.5
- tcpsock:receiveuntil yuansheng-10.5
- tcpsock:close yuansheng-10.5
- tcpsock:settimeout yuansheng-10.5
- tcpsock:setoption yuansheng-10.5
- tcpsock:setkeepalive yuansheng-10.5
- tcpsock:getreusedtimes yuansheng-10.5
- ngx.socket.connect yuansheng-10.4
- ngx.get_phase yuansheng-10.2
- ngx.thread.spawn yuansheng-10.2
- ngx.thread.wait yuansheng-10.4
- ngx.thread.kill yuansheng-10.4
- ngx.on_abort yuansheng-10.2
- ngx.timer.at yuansheng-10.1
- ngx.config.debug yuansheng-9.30
- ngx.config.prefix yuansheng-9.30
- ngx.config.nginx_version yuansheng-9.30
- ngx.config.nginx_configure yuansheng-9.30
- ngx.config.ngx_lua_version yuansheng-9.30
- ngx.worker.exiting yuansheng-9.30
- ngx.worker.pid yuansheng-9.30
- ndk.set_var.DIRECTIVE yuansheng-9.30
- coroutine.create yuansheng-9.30
- coroutine.resume yuansheng-9.30
- coroutine.yield yuansheng-9.30
- coroutine.wrap yuansheng-9.30
- coroutine.running yuansheng-9.30
- coroutine.status yuansheng-9.30