lua_package_path “conf/lua/?.lua”; 表示多个字符串的通配符为?,不是 *
lua中涉及到路径,如果没有指定绝对路径,那前缀为 安装 openresty 的 路径前缀。比如
1234567891011121314151617181920lua_package_path "lua/?.lua" :路径为/usr/local/openresty/lua/?.luaaccess_by_lua_file lua/access_check.lua : 路径为/usr/local/openresty/lua/access_check.lua```3. ngx.var.arg_a : 获取url中参数a的值;ngx.var.内部变量名:获取内部变量值,如ngx.var.remote_addr 获取访问用户地址Setting ngx.var.Foo to a nil value will unset the $Foo Nginx variable.```luangx.var.args = nil```4. ngx.var.limit_rate = 1000 限速,注意:并不是每个nginx内置变量都可以改变。5. 如果需要在Lua中处理错误,必须使用函数pcall(protected call)来包装需要执行的代码。 pcall接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值true或者或false, errorinfo。pcall以一种"保护模式"来调用第一个参数,因此pcall可以捕获函数执行中的任何错误。```luapcall(function (str) json_value = json.decode(str) end, str)
debug
1lua_code_cache off;修改完代码后,不用reload nginx就可以生效了。在生产环境下记得打开这个选项。
读取post数据:curl -XPOST ‘xxxxx/test’ -d ‘a=xxx&b=yyy’
12ngx.req.read_body() -- explicitly read the req bodylocal data = ngx.req.get_body_data() => a=xxx&b=yyy
local file = ngx.req.get_body_file() 获取文件内容
1curl -XPOST 'xxxxx/test' -d '@/etc/passwd' file的值为本地文件/etc/passwd的内容。ngx.location.capture
123456789101112res = ngx.location.capture("/some_other_location")```res结果是 http://xxxxx/some_other_location 这个链接的输出。Issuing a POST subrequest, for example, can be done as follows```luares = ngx.location.capture('/foo/bar',{ method = ngx.HTTP_POST, body = 'hello, world' })
res包括:
res.status, res.header, res.body, and res.truncated
The args option can specify extra URI arguments, for instance,
|
|
is equivalent to
|
|
that is, this method will escape argument keys and values according to URI rules and concatenate them together into a complete query string. The format for the Lua table passed as the args argument is identical to the format used in thengx.encode_args method.
The args option can also take plain query strings:
|
|
ngx.location.capture_multi :同时捕获多个链接输出
The ngx.location.capture and ngx.location.capture_multi directives cannot capture locations that include the add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest, or echo_subrequest_async directives.
|
|
Lua tables can be used for both requests and responses when the number of subrequests to be issued is not known in advance:
|
|
Capture
1234location ~ ^/app/([-_a-zA-Z0-9/]+) {set $path $1; $1为location中匹配到的部分content_by_lua_file /path/to/lua/app/root/$path.lua;}
重定向
1ngx.redirect("/terms_of_use.html") :重定向
伪异步
1nginx.eof():
与客户端断开连接,但是继续向下执行以后的代码,此时nginx进程还没有释放,类似php的fastcgi_request_finish.
ngx.say && ngx.print
1ngx.say、ngx.print:功能一样,say会额外输出一个换行
set
123set $foo 32;set_by_lua $bar 'return tonumber(ngx.var.foo) + 1';set $baz "bar: $bar"; # $baz == "bar: 33"
header_filter_by_lua:增加response header
1234location / {proxy_pass http://mybackend;header_filter_by_lua 'ngx.header.Foo = "blah"';}
ngx.arg
When this is used in the context of the set_by_lua or set_by_lua_file directives, this table is read-only and holds the input arguments to the config directives:
1value = ngx.arg[n]
Here is an example
12345678
location /foo { set $a 32; set $b 56; set_by_lua $sum 'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])' $a $b; echo $sum; }
that writes out 88, the sum of 32 and 56.
HTTP方法常量
123456789101112131415ngx.HTTP_GETngx.HTTP_HEADngx.HTTP_PUTngx.HTTP_POSTngx.HTTP_DELETEngx.HTTP_OPTIONS (added in the v0.5.0rc24 release)ngx.HTTP_MKCOL (added in the v0.8.2 release)ngx.HTTP_COPY (added in the v0.8.2 release)ngx.HTTP_MOVE (added in the v0.8.2 release)ngx.HTTP_PROPFIND (added in the v0.8.2 release)ngx.HTTP_PROPPATCH (added in the v0.8.2 release)ngx.HTTP_LOCK (added in the v0.8.2 release)ngx.HTTP_UNLOCK (added in the v0.8.2 release)ngx.HTTP_PATCH (added in the v0.8.2 release)ngx.HTTP_TRACE (added in the v0.8.2 release)
HTTP status常量
1234567891011121314151617value = ngx.HTTP_OK (200)value = ngx.HTTP_CREATED (201)value = ngx.HTTP_SPECIAL_RESPONSE (300)value = ngx.HTTP_MOVED_PERMANENTLY (301)value = ngx.HTTP_MOVED_TEMPORARILY (302)value = ngx.HTTP_SEE_OTHER (303)value = ngx.HTTP_NOT_MODIFIED (304)value = ngx.HTTP_BAD_REQUEST (400)value = ngx.HTTP_UNAUTHORIZED (401)value = ngx.HTTP_FORBIDDEN (403)value = ngx.HTTP_NOT_FOUND (404)value = ngx.HTTP_NOT_ALLOWED (405)value = ngx.HTTP_GONE (410)value = ngx.HTTP_INTERNAL_SERVER_ERROR (500)value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)value = ngx.HTTP_SERVICE_UNAVAILABLE (503)value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release)
Nginx log level constants
123456789ngx.STDERRngx.EMERGngx.ALERTngx.CRITngx.ERRngx.WARNngx.NOTICEngx.INFOngx.DEBUG
ngx.ctx:在一个请求中传递变量
This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables).
Consider the following example,1234567891011121314151617location /test {rewrite_by_lua 'ngx.ctx.foo = 76';access_by_lua 'ngx.ctx.foo = ngx.ctx.foo + 3';content_by_lua 'ngx.say(ngx.ctx.foo)';}```Then GET /test will yield the output```lua79
That is, the ngx.ctx.foo entry persists across the rewrite, access, and content phases of a request.
Every request, including subrequests, has its own copy of the table. For example:
123456789101112131415161718
location /sub { content_by_lua ' ngx.say("sub pre: ", ngx.ctx.blah) ngx.ctx.blah = 32 ngx.say("sub post: ", ngx.ctx.blah) ';}location /main { content_by_lua ' ngx.ctx.blah = 73 ngx.say("main pre: ", ngx.ctx.blah) local res = ngx.location.capture("/sub") ngx.print(res.body) ngx.say("main post: ", ngx.ctx.blah) ';}
Then GET /main will give the output
1234
main pre: 73sub pre: nilsub post: 32main post: 73
Here, modification of the ngx.ctx.blah entry in the subrequest does not affect the one in the parent request. This is because they have two separate versions of ngx.ctx.blah.
Internal redirection will destroy the original request ngx.ctx data (if any) and the new request will have an empty ngx.ctxtable. For instance,
123456789101112
location /new { content_by_lua ' ngx.say(ngx.ctx.foo) ';} location /orig { content_by_lua ' ngx.ctx.foo = "hello" ngx.exec("/new") ';}
Then GET /orig will give
1
nil
ngx.status:设置或获取nginx status
12ngx.status = ngx.HTTP_CREATEDstatus = ngx.statusSetting ngx.status after the response header is sent out has no effect,but leaving an error message in your nginx’s error log file:
attempt to set ngx.status after sending out response headersngx.header.HEADER
syntax: ngx.header.HEADER = VALUE
syntax: value = ngx.header.HEADER
header name中的下划线默认会被替换成中划线,lua_transform_underscores_in_response_headers可以关闭。
The header names are matched1case-insensitively:大小写不敏感.1234567891011-- equivalent to ngx.header["Content-Type"] = 'text/plain'ngx.header.content_type = 'text/plain';ngx.header["X-My-Header"] = 'blah blah';Multi-value headers can be set this way:ngx.header['Set-Cookie'] = {'a=32; path=/', 'b=4; path=/'}will yieldSet-Cookie: a=32; path=/Set-Cookie: b=4; path=/in the response headers.
Setting a slot to nil effectively removes it from the response headers:
1ngx.header["X-My-Header"] = nil;
The same applies to assigning an empty table:
1
ngx.header["X-My-Header"] = {};
This is particularly useful in the context of header_filter_by_lua and header_filter_by_lua_file, for example,
12345678910111213
location /test { set $footer ''; proxy_pass http://some-backend; header_filter_by_lua ' if ngx.header["X-My-Header"] == "blah" then ngx.var.footer = "some value" end '; echo_after_body $footer;}
For multi-value headers, all of the values of header will be collected in order and returned as a Lua table. For example, response headers Foo: bar Foo: baz
will result in
1
{"bar", "baz"}
to be returned when reading ngx.header.Foo.
ngx.resp.get_headers/ngx.req.get_headers:获取header
syntax: headers = ngx.resp.get_headers(max_headers?, raw?)
context: set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_lua, body_filter_by_lua, log_by_lua**Returns a Lua table holding all the current response headers for the current request.
12345678910111213local h = ngx.req.get_headers()for k, v in pairs(h) dongx.say("Req Header ---> " .. k .. "==> ' .. v)endlocal h = ngx.resp.get_headers()for k, v in pairs(h) dongx.say("Resp Header <---- " .. k .. "==> ' .. v)endheader_filter_by_lua_block {ngx.header.X-Foo-bar = "Hit"}ngx.req.start_time:返回当前请求被创建的时间
1local request_time = ngx.now() - ngx.req.start_time()
ngx.req.http_version获取 http 版本
ngx.req.raw_header(bool no_request_line):获取原始header字符串
参数no_request_line决定是否返回 ‘GET /t HTTP/1.1’ 类似的请求信息
ngx.req.get_method()、ngx.req.set_method:获取、设置method
ngx.req.set_uri
syntax: ngx.req.set_uri(uri, jump?)
For instance, Nginx config1rewrite ^ /foo?a=3? last;
can be coded as
12
ngx.req.set_uri_args("a=3")ngx.req.set_uri("/foo", true)
or
12
ngx.req.set_uri_args({a = 3})ngx.req.set_uri("/foo", true)
ngx.req.set_uri_args
123ngx.req.set_uri_args("a=3&b=hello%20world")ngx.req.set_uri_args({ a = 3, b = "hello world" }) 效果相同ngx.req.set_uri_args({ a = 3, b = {5, 6} }) --> a=3&b=5&b=6.
ngx.req.get_uri_args:获取url参数
123456789101112location = /test {content_by_lua 'local args = ngx.req.get_uri_args()for key, val in pairs(args) doif type(val) == "table" thenngx.say(key, ": ", table.concat(val, ", "))elsengx.say(key, ": ", val)endend';}Then GET /test?foo=bar&bar=baz&bar=blah will yield the response body
12foo: barbar: baz, blah
Arguments without the = parts are treated as boolean arguments. GET /test?foo&bar will yield:
12
foo: truebar: true
GET /test?foo=&bar= will give something like
12
foo:bar:
Updating query arguments via the nginx variable $args (or ngx.var.args in Lua) at runtime is also supported:
12
ngx.var.args = "a=3&b=42"local args = ngx.req.get_uri_args()
Here the args table will always look like
1
{a = 3, b = 42}
在一个nignx worker内共享数据
123456789101112131415161718192021222324252627282930313233-- mydata.lualocal _M = {}local data = {dog = 3,cat = 4,pig = 5,}function _M.get_age(name)return data[name]endfunction _M.set_age(name,value)data[name] = valueendreturn _Mlocation /lua {content_by_lua 'local mydata = require "mydata"ngx.say(mydata.get_age("dog"))mydata.set_age("dog",1111)';}```连续访问两次,第一次输出3 ,第二次输出1111注意:需要以下设置才能生效:```luaworker_processes 1; //多个进程时,可能需要刷新多次才能出现lua_code_cache on;
最后:
- 尽量在声明变量时使用local
- 使用ngx.var,ngx.print等的时候也尽量设定为本地变量
- 错误处理需要使用pcall 包装要执行的代码
- 使用require加载模块
- 请求返回可以继续执行任务(fastcgi_finish, ngx.eof()) 尾调用
- 连接池使用(set_keep_alive, redis/mysql要用)
- 数组下标1 #aa 可以获取数组大小,但是千万不要使用
ffi的使用
参考: phper