--[[
test
--]]
ngx.header.content_type = "text/plain"; --输出头部
local user = ngx.var.arg_user -- 定义user变量并获取url中的参数 http://localhost?user=hello
local sys = ngx.var.server_name -- 获取nginx中的变量
ngx.say (user); -- 输出至页面
ngx.say (sys);
if user== "spam" then
local res=ngx.location.capture("/lua") -- capture
if res.status == 200 then
ngx.print("capture:",res.body)
end
end
tbl = {"alpha", "beta", "gamma"} --定义table 数组
table.insert(tbl, "delta") --增加数组元素
table.sort( tbl, sortLevelNameAsc ) -- 数组排序
for i = 1, table.getn(tbl) do -- for循环
ngx.say(string.format("%s", tbl[i])) -- string format
end
local deled=table.remove(tbl, 2) -- 删除指定位置元素并返回删除元素.如果没有指定删除的位置,则默认删除table的最后一个元素
ngx.say ("delete the second element " .. deled ) -- 字符串连接 .. gTable = {}
gTable.name = "eric"
gTable.gender = "man"
gTable.phonenumber = "0000000000"
gTable[1] = "公司"
gTable[2] = "部门"
gTable.hobby = {"跑步", "读书", "游戏", "动漫"} -- 多维table,可以通过gTable.hobby[1]的方式访问.即gTable.hobby本身也是一个table
gTable.secTable = {}
gTable.secTable.job = "程序员"
gTable.secTable.label = "写代码的"
gTable.secTable.description = "职责是实现产品的逻辑"
for index, value in pairs(gTable) do
ngx.say(string.format("%s:%s", index, value)) -- string format
if ("table" == type(value)) then
for idx, var in pairs(value) do
ngx.say(string.format("二维table:%s:%s", idx, var)) -- string format
end
end
end
--[[
输出结果如下:
1 公司
2 部门
hobby table: 0x7fdceac14bc0
二维table: 1 跑步
二维table: 2 读书
二维table: 3 游戏
二维table: 4 动漫
phonenumber 0000000000
gender man
secTable table: 0x7fdceac15100
二维table: label 写代码的
二维table: description 职责是实现产品的逻辑
二维table: job 程序员
name eric
--]]
ngx.say (table.concat( tbl, ":")) -- join
ngx.say(#tbl) -- 返回数组个数
ngx.say(os.time()) -- 1423643892
ngx.say(os.date()) -- Wed Feb 11 16:38:12 2015
ngx.say(os.date("%m/%d/%Y",os.time())) -- 02/11/2015
ngx.say(os.date("%Y-%m-%d %H:%M:%S",1423643892)) -- 2015-02-11 16:38:12 time to date
ngx.say(os.time{year="2015", month="2", day="11", hour="16",min="38",sec="12"}) -- 1423643892 date to time ngx.say(tonumber("100")+11) --字符与数字的显式转换 输出结果为:111
ngx.say(type(tostring(100))) --转换成字符串 并获取类型 输出结果为:string
ngx.say(string.len("hello")) --字符串长度 输出结果为:5
ngx.say(string.sub("hello Lua", 7,9)) --截取字符串 输出结果为:Lua
ngx.say(math.random(1,2)); --随机数
ngx.print(ngx.req.raw_header(),ngx.var.uri) -- 获取http header 信息
--[[
获取ip
--]]
local function getip( )
local 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
return myIP
end
ngx.print(getip()) --调取函数 按顺序,必须先申明方法 才能调用
ngx.redirect("http://www.elong.com") --跳转 
 

 多行字符串

local longstring=[[123
456
abc
'szSuffix'
]]
ngx.say(longstring)

ngx_lua安装

ngx_lua安装可以通过下载模块源码,编译Nginx,但是推荐采用openresty。Openresty就是一个打包程序,包含大量的第三方Nginx模块,比如HttpLuaModule,HttpRedis2Module,HttpEchoModule等。省去下载模块,并且安装非常方便。

ngx_openresty bundle: openresty

./configure --with-luajit&& make && make install

默认Openresty中ngx_lua模块采用的是标准的Lua5.1解释器,通过--with-luajit使用LuaJIT。

ngx.location.capture

location = /other {
ehco 'Hello, world!';
} # Lua非阻塞IO
location = /lua {
content_by_lua '
local res = ngx.location.capture("/other?id=12")
if res.status == then
ngx.print(res.body)
end
';
}

capture post

-- POST https://www.example.com:443/foo/bar?hello=world
ngx.req.set_header("Content-Type", "application/json;charset=utf8");
ngx.req.set_header("Accept", "application/json"); local res = ngx.location.capture('/proxy/https/www.example.com/443/foo/bar', {
method = ngx.HTTP_POST,
body = body,
args = {hello = 'world'}
});

ngx.location.capture_multi

语法:res1,res2, ... = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, ...})

与ngx.location.capture功能一样,可以并行的、非阻塞的发出多个子请求。这个方法在所有子请求处理完成后返回,并且整个方法的运行时间取决于运行时间最长的子请求,并不是所有子请求的运行时间之和。

# 同时发送多个子请求(subrequest)
location = /moon {
ehco 'moon';
}
location = /earth {
ehco 'earth';
} location = /lua {
content_by_lua '
local res1,res2 = ngx.location.capture_multi({ {"/moon"}, {"earth"} })
if res1.status == then
ngx.print(res1.body)
end
ngx.print(",")
if res2.status == then
ngx.print(res2.body)
end
';
}

set_by_lua

和set指令一样用于设置Nginx变量并且在rewrite阶段执行,只不过这个变量是由lua脚本计算并返回的。

语法:set_by_lua$res <lua-script-str> [$arg1 $arg2 ...]

location = /adder {
set_by_lua $res "
local a = tonumber(ngx.arg[])
local b = tonumber(ngx.arg[])
return a + b" $arg_a $arg_b; echo $res;
}

set_by_lua_file

执行Nginx外部的lua脚本,可以避免在配置文件中使用大量的转义

location = /fib {
set_by_lua_file $res "conf/adder.lua" $arg_n; echo $res;
}  adder.lua:

local a = tonumber(ngx.arg[1])

local b = tonumber(ngx.arg[2])

return a + b

 

access_by_lua和access_by_lua_file

运行在access阶段,用于访问控制。Nginx原生的allow和deny是基于ip的,通过access_by_lua能完成复杂的访问控制,比如,访问数据库进行用户名、密码验证等。

location /auth {
access_by_lua '
if ngx.var.arg_user == "ntes" then
return
else
Ngx.exit(ngx.HTTP_FORBIDDEN)
end
';
echo 'welcome ntes';
}

输出:

$ curl 'localhost/auth?user=sohu'
$ Welcome ntes $ curl 'localhost/auth?user=ntes'
$ <html>
<head><title> Forbidden</title></heda>
<body bgcolor="white">
<center><h1> Forbidden</h1></center>
<hr><center>ngx_openresty/1.0.10.48</center>
</body>
</html>

rewrite_by_lua和rewrite_by_lua_file

实现url重写,在rewrite阶段执行。

配置:

location = /foo {
rewrite_by_lua 'ngx.exec("/bar")';
echo 'in foo';
} location = /bar {
echo 'Hello, Lua!';
}

输出:

$ curl 'localhost/lua'
$ Hello, Lua!

content_by_lua和content_by_lua_file

Contenthandler在content阶段执行,生成http响应。由于content阶段只能有一个handler,所以在与echo模块使用时,不能同时生效,我测试的结果是content_by_lua会覆盖echo。这和之前的hello world的例子是类似的。

location = /lua {
content_by_lua 'ngx.say("Hello, Lua!")';
}

os.execute ([command])
功能:相当于C的system函数,返回系统状态码

例如:
os.execute("pause")

输出:
按任意键继续. . .

os.exit ([code])
功能:相当于C的exit函数,终止主程序,code为返回值

例如:
os.exit(1)

os.getenv (varname)

例如:

print(os.getenv("USERDOMAIN"))
print(os.getenv("SystemRoot"))
print(os.getenv("Os2LibPath"))
print(os.getenv("ProgramFiles" ))
print(os.getenv("APPDATA" ))
print(os.getenv("ALLUSERSPROFILE" ))
print(os.getenv("CommonProgramFiles" ))
print(os.getenv("COMPUTERNAME" ))
print(os.getenv("USERNAME"))
print(os.getenv("USERPROFILE" ))
print(os.getenv("ComSpec"))
print(os.getenv("LOGONSERVER" ))
print(os.getenv("NUMBER_OF_PROCESSORS" ))
print(os.getenv("OS"))
print(os.getenv("PATHEXT" ))
print(os.getenv("PROCESSOR_ARCHITECTURE" ))
print(os.getenv("PROCESSOR_IDENTIFIER" ))
print(os.getenv("PROCESSOR_LEVEL" ))
print(os.getenv("PROCESSOR_REVISION" ))
print(os.getenv("USERDOMAIN"))
print(os.getenv("SystemRoot" ))
print(os.getenv("TEMP"))

输出:

RDEV
C:\WINDOWS
nil
C:\Program Files
C:\Documents and Settings\baiyun\Application Data
C:\Documents and Settings\All Users
C:\Program Files\Common Files
BAIYUN
baiyun
C:\Documents and Settings\baiyun
C:\WINDOWS\system32\cmd.exe
http://www.cnblogs.com/whiteyun/admin/file://rdev1/ Windows_NT
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.py;.pyw;.wlua
x86
x86 Family Model Stepping , GenuineIntel RDEV
C:\WINDOWS
C:\DOCUME~\baiyun\LOCALS~\Temp

os.remove (filename)
功能:删除文件或一个空目录,若函数调用失败则返加nil加错误信息

os.rename (oldname, newname)
功能:更改一个文件或目录名,若函数调用失败则返加nil加错误信息

调取 mysql json redis操作

ngx.say("=============== mysql ==============")
local mysql = require "resty.mysql"
local db,err = mysql:new()
if not db then
ngx.say("failed to instantiate mysql: ",err)
return
end
db:set_timeout()
local ok,err,errno,sqlstate = db:connect{
host = "127.0.0.1",
port = ,
database = "el_agency",
user = "root",
password = "",
max_package_size =
}
if not ok then
ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
return
end
db:query("set names utf8")
ngx.say("connected to mysql.")
res,err,errno,sqlstate = db:query("select username,appKey,secretKey from tbl_user limit 2")
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
db:close()
ngx.say("=============== cjson ==============") local cjson = require "cjson";
local res1=cjson.encode(res);
ngx.say(res1);
local res2=cjson.decode(res1);
print_lua_table(res2); ngx.say("=============== redis ==============")
local redis = require("resty.redis")
local client = redis:new()
client:set_timeout() -- 1 second
local ok,err = client:connect("127.0.0.1",)
if not ok then
ngx.say("failed to connect: ",err)
return
end
client:set("hello","world");
local res,err = client:get("hello")
if not res then
ngx.say("failed to get",err)
return
end
client:close()
ngx.say(res)

执行顺序

.init_by_lua  上下文http  ngx启动时执行
.set_by_lua 上下文 server, server if, location, location if
.rewrite_by_lua 上下文 http, server, location, location if
.access_by_lua 上下文 http, server, location, location if
.content_by_lua 上下文 location, location if
.header_filter_by_lua 上下文 http, server, location, location if
.body_filter_by_lua 上下文 http, server, location, location if
.log_by_lua 上下文 http, server, location, location if

 lua中 三目运算符的实现

(a and b) or c <==> a ? b : c

 lua urlencode urldecode URL编码

function decodeURI(s)
s = string.gsub(s, '%%(%x%x)', function(h) return string.char(tonumber(h, )) end)
return s
end function encodeURI(s)
s = string.gsub(s, "([^%w%.%- ])", function(c) return string.format("%%%02X", string.byte(c)) end)
return string.gsub(s, " ", "+")
end 或者
ngx.escape_uri() 字符串的url编码
ngx.unescape_uri() 字符串url解码
 

  LUA require 搜索路径指定方法

如果是一个 *.LUA 的文件, 里面用到了自己写的库, 或者第三方写的库, 但是你不想把它放到 lua 的安装目录里, 则在代码里面可以指定require搜索的路径。

    package.path = '/usr/local/share/lua/5.1/?.lua;/home/resty/?.lua;;'    --搜索lua模块 ;;指定默认路径
package.cpath = '/usr/local/lib/lua/5.1/?.so;;' --搜索so模块 如果是要在 nginx.conf 文件中引用第三方的库,则需要在 http 段中添加下面的代码 lua_package_path '/usr/local/share/lua/5.1/?.lua;/home/resty/?.lua;';
lua_package_cpath '/usr/local/lib/lua/5.1/?.so;';

lua下面dump出一个table的结构

--- @brief 调试时打印变量的值
--- @param data 要打印的字符串
--- @param [max_level] table要展开打印的计数,默认nil表示全部展开
--- @param [prefix] 用于在递归时传递缩进,该参数不供用户使用于
--- @ref http://dearymz.blog.163.com/blog/static/205657420089251655186/
function var_dump(data, max_level, prefix)
if type(prefix) ~= "string" then
prefix = ""
end
if type(data) ~= "table" then
print(prefix .. tostring(data))
else
print(data)
if max_level ~= then
local prefix_next = prefix .. " "
print(prefix .. "{")
for k,v in pairs(data) do
io.stdout:write(prefix_next .. k .. " = ")
if type(v) ~= "table" or (type(max_level) == "number" and max_level <= ) then
print(v)
else
if max_level == nil then
var_dump(v, nil, prefix_next)
else
var_dump(v, max_level - , prefix_next)
end
end
end
print(prefix .. "}")
end
end
end

ngx.exec

 location @cc {
internal;
root html;
index index.html index.htm;
} 代码中
ngx.exec("@cc")

iptolong

-- 参数:待分割的字符串,分割字符
-- 返回:子串表.(含有空串)
function split(s, delim)
if type(delim) ~= "string" or string.len(delim) <= then
return
end local start =
local t = {}
while true do
local pos = string.find (s, delim, start, true) -- plain find
if not pos then
break
end table.insert (t, string.sub (s, start, pos - ))
start = pos + string.len (delim)
end
table.insert (t, string.sub (s, start)) return t
end --ip转整数
function ip2long(ip)
local ips=split(ip,".")
local num =
for i,v in pairs(ips) do
num =num +(tonumber(v) * math.pow(,#ips-i))
end
return num
end

获取当前路径及上级目录

function dirname(str)
if str:match(".-/.-") then
local name = string.gsub(str, "(.*/)(.+)", "%1")
return name
elseif str:match(".-\\.-") then
local name = string.gsub(str, "(.*\\)(.+)", "%1")
return name
else
return ''
end
end local __FILE__ = debug.getinfo(,'S').source:sub()
ROOT_PATH=dirname(__FILE__)

lua 创建一个“类” 并返回“类”中的所有方法

--helper.lua

local _M = { _VERSION = '0.09' }

function _M.to_hex(s)

end

function _M.atoi (s)

end

return _M

local helper=require 'helper'

var_dump(helper)

返回

["to_hex"] = function: 0x0cd26038,
["atoi"] = function: 0x0cd260e8,
["_VERSION"] = "0.09",

package.seeall

--game.lua
module(..., package.seeall) --- ...不定参数
function play()
return "ok just do it"end
function quit()
return "welcome back again"end

--require
local game=require 'game'
ngx.say(game:play())

 Nginx中Lua模块的运行机制

Nginx中的每个Worker进程使用一个lua虚拟机,工作进程中的所有协程共享虚拟机。将Nginx中的lua API封装好之后注入到lua的VM中就可以在lua代码中进行访问

异常捕获pcall

local user = ngx.var.arg_user
local st,err=pcall(function()
if user == "spam" then
local res=ngx.location.capture("/lua") -- capture
if res.status == then
ngx.print("capture:",res.body)
end
else
error("出错啦")
end
end); if not st then
ngx.say(err)
end ----类似于php try{
  if (user == "spam"){
//todo
}else{
throw New Exception("出错啦")
}
}catch(Exception $ex){
echo $ex->getMessage();
}

ngx_lua 随笔的更多相关文章

  1. AI人工智能系列随笔

    初探 AI人工智能系列随笔:syntaxnet 初探(1)

  2. 【置顶】CoreCLR系列随笔

    CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...

  3. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  4. C++随笔:从Hello World 探秘CoreCLR的内部(1)

    紧接着上次的问题,上次的问题其实很简单,就是HelloWorld.exe运行失败,而本文的目的,就是成功调试HelloWorld这个控制台应用程序. 通过我的寻找,其实是一个名为TryRun的文件出了 ...

  5. ASP.NET MVC 系列随笔汇总[未完待续……]

    ASP.NET MVC 系列随笔汇总[未完待续……] 为了方便大家浏览所以整理一下,有的系列篇幅中不是很全面以后会慢慢的补全的. 学前篇之: ASP.NET MVC学前篇之扩展方法.链式编程 ASP. ...

  6. 使用Beautiful Soup编写一个爬虫 系列随笔汇总

    这几篇博文只是为了记录学习Beautiful Soup的过程,不仅方便自己以后查看,也许能帮到同样在学习这个技术的朋友.通过学习Beautiful Soup基础知识 完成了一个简单的爬虫服务:从all ...

  7. 利用Python进行数据分析 基础系列随笔汇总

    一共 15 篇随笔,主要是为了记录数据分析过程中的一些小 demo,分享给其他需要的网友,更为了方便以后自己查看,15 篇随笔,每篇内容基本都是以一句说明加一段代码的方式, 保持简单小巧,看起来也清晰 ...

  8. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  9. 《高性能javascript》 领悟随笔之-------DOM编程篇

    <高性能javascript> 领悟随笔之-------DOM编程篇一 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

随机推荐

  1. OpenStack 部署总结之:单节点icehouse网桥的配置

    部署完icehouse,安装完实例之后.假设虚拟主机须要和外部进行通信.还须要对宿主机的网桥进行配置 宿主机的配置 改动ifcfg-em1的内容为下面内容: DEVICE=em1 ONBOOT=yes ...

  2. PHP快速入门 常用配置

    1 打开php.ini-dist文件 2 查找"file_uploads",确定为On(确定服务器上的 PHP 脚本是否可以接受文件上传.) 3 查找"max_execu ...

  3. source insight中{}自动缩进的调整

    默认的自动缩进非常难看,解决方法如下: 菜单栏 -> Options -> document options ->点击右侧的 “Auto Indent...”按钮 将右侧" ...

  4. vb.net Bitmap Drawing

    Public Class Form1 Dim BMP As New Drawing.Bitmap(640, 480) Dim GFX As Graphics = Graphics.FromImage( ...

  5. 七彩花都手机客户部分测试源码Phonegap+html5

    个人建设广州花都论坛,七彩花都(http://www.w30.cn)包含传值回复楼层的jsonp 可以加入我们的QQ群讨论 专注phonepap 核心加载 jsonp返回格式为 jsonp([{&qu ...

  6. TP框架项目部署linux大小写问题

    TP框架项目部署linux大小写问题

  7. taro 打包微信小程序运行失败(一)

    1.报错信息 thirdScriptError sdk uncaught third Error Cannot read property 'createTextNode' of undefined ...

  8. sqlserver2008 R2中查找未使用过的索引

    转自:http://blog.csdn.net/yangzhawen/article/details/7247393 sqlserver2008 R2中查找未使用过的索引: o.name AS 表名 ...

  9. java 线程安全集合

    ConcurrentMap 线程安全的HashMap CopyOnWriteArrayList 读多写少的线程安全的ArrayList,性能比vector好. ConcurrentLinkedQueu ...

  10. 【故障处理141119】一次数据库不繁忙时一条sql语句2个运行计划导致业务超时的故障处理

    1,故障描写叙述: 一条select有两个运行计划.在sqlplus中运行选择好的运行计划.仅仅要40毫秒.而在程序中运行选择了差的运行计划,要1分23秒左右,导致前台业务超时报错. 2.故障解决: ...