转载请标明出处:

http://blog.csdn.net/forezp/article/details/78616660

本文出自方志朋的博客

获取请求参数

vim /usr/example/example.conf

 location /lua_var {
default_type 'text/plain';
content_by_lua_block {
ngx.say(ngx.var.arg_a)
}
}

重新加载nginx配置文件: nginx -s reload

在浏览器上访问http://116.196.177.123/lua_var?a=323,浏览器显示:

323

在上述代码中,涉及到了2个api, 一是ngx.say(直接返回请求结果);二是ngx.var,它是获取请求的参数,比如本例子上的?a=323,获取之后,直接输出为请求结果。

获取请求类型

vim /usr/example/example.conf

  location /lua_request{
default_type 'text/html';
lua_code_cache off;
content_by_lua_file /usr/example/lua/lua_request.lua;
}

vim /usr/example/lua/lua_request.lua ,添加一下代码:


local arg = ngx.req.get_uri_args()
for k,v in pairs(arg) do
ngx.say("[GET ] key:", k, " v:", v)
end ngx.req.read_body() -- 解析 body 参数之前一定要先读取 body
local arg = ngx.req.get_post_args()
for k,v in pairs(arg) do
ngx.say("[POST] key:", k, " v:", v)
end

在上述例子中有以下的api:

  • ngx.req.get_uri_args 获取在uri上的get类型参数,返回的是一个table类型的数据结构。
  • ngx.req.read_body 读取body,这在解析body之前,一定要先读取body。
  • ngx.req.get_post_args 获取form表单类型的参数,返回结果是一个table类型的数据。

使用curl模拟请求:

curl ‘http://116.196.177.123/lua_request?a=323&b=ss’ -d ‘c=12w&d=2se3’

返回的结果:

[GET ] key:b v:ss
[GET ] key:a v:323
[POST] key:d v:2se3
[POST] key:c v:12w

获取请求头

vim /usr/example/lua/lua_request.lua ,在原有的代码基础上,再添加一下代码:


local headers = ngx.req.get_headers()
ngx.say("headers begin", "<br/>")
ngx.say("Host : ", headers["Host"], "<br/>")
ngx.say("user-agent : ", headers["user-agent"], "<br/>")
ngx.say("user-agent : ", headers.user_agent, "<br/>")
for k,v in pairs(headers) do
if type(v) == "table" then
ngx.say(k, " : ", table.concat(v, ","), "<br/>")
else
ngx.say(k, " : ", v, "<br/>")
end
end

重新加载nginx -s reload

使用curl模拟请求:

curl ‘http://116.196.177.123/lua_request?a=323&b=ss’ -d ‘c=12w&d=2se3’

[GET ] key:b v:ss
[GET ] key:a v:323
[POST] key:d v:2se3
[POST] key:c v:12w
headers begin<br/>
Host : 116.196.77.157<br/>
user-agent : curl/7.53.0<br/>
user-agent : curl/7.53.0<br/>
host : 116.196.77.157<br/>
content-type : application/x-www-form-urlencoded<br/>
accept : */*<br/>
content-length : 12<br/>
user-agent : curl/7.53.0<br/>

获取http的其他方法

vim /usr/example/lua/lua_request.lua ,在原有的代码基础上,再添加一下代码:

ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>")
--请求方法
ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>")
--原始的请求头内容
ngx.say("ngx.req.raw_header : ", ngx.req.raw_header(), "<br/>")
--请求的body内容体
ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>")
ngx.say("<br/>")

重新加载nginx -s reload

使用curl模拟请求:

curl ‘http://116.196.177.123/lua_request?a=323&b=ss’ -d ‘c=12w&d=2se3’

//....
ngx.req.http_version : 1.1<br/>
ngx.req.get_method : POST<br/>
ngx.req.raw_header : POST /lua_request?a=323&b=ss HTTP/1.1
Host: 116.196.77.157
User-Agent: curl/7.53.0
Accept: */*
Content-Length: 12

输出响应

vim /usr/example/example.conf,添加一个location,代码如下:

 location /lua_response{
default_type 'text/html';
lua_code_cache off;
content_by_lua_file /usr/example/lua/lua_response.lua ;
}

vim /usr/example/lua/lua_response.lua 添加一下代码:

ngx.header.a="1"
ngx.header.b={"a","b"}
ngx.say("hello","</br>")
ngx.print("sss")
return ngx.exit(200)

上述代码中有以下api:

  • ngx.header 向响应头输出内容
  • ngx.say 输出响应体
  • ngx.print输出响应体
  • ngx.exit 指定http状态码退出

使用curl模拟请求, curl ‘http://116.196.177.123/lua_response’ ,获取的响应体如下:

hello
sss

日志输出

在配置文件vim /usr/example/example.conf 加上以下代码:

 location /lua_log{
default_type 'text/html';
lua_code_cache off;
content_by_lua_file /usr/example/lua/lua_log.lua;
}

vim /usr/example/lua/lua_log.lua ,加上以下代码:


local log="i'm log"
local num =10
ngx.log(ngx.ERR, "log",log)
ngx.log(ngx.INFO,"num:" ,num)

重新加载配置文件nginx -s reload

curl ‘http://116.196.177.123/lua_log

打开nginx 的logs目录下的error.log 文件:

tail -fn 1000 /usr/servers/nginx/logs/error.log

可以看到在日志文件中已经输出了日志,这种日志主要用于记录和测试。

日志级别:

  • ngx.STDERR – 标准输出
  • ngx.EMERG – 紧急报错
  • ngx.ALERT – 报警
  • ngx.CRIT – 严重,系统故障,触发运维告警系统
  • ngx.ERR – 错误,业务不可恢复性错误
  • ngx.WARN – 告警,业务中可忽略错误
  • ngx.NOTICE – 提醒,业务比较重要信息
  • ngx.INFO – 信息,业务琐碎日志信息,包含不同情况判断等
  • ngx.DEBUG – 调试

内部调用

vim /usr/example/example.conf 添加以下代码:

location /lua_sum{
# 只允许内部调用
internal;
# 这里做了一个求和运算只是一个例子,可以在这里完成一些数据库、
# 缓存服务器的操作,达到基础模块和业务逻辑分离目的
content_by_lua_block {
local args = ngx.req.get_uri_args()
ngx.say(tonumber(args.a) + tonumber(args.b))
}
}

internal 关键字,表示只允许内部调用。使用curl模拟请求,请求命令如下:

$ curl ‘http://116.196.177.123/lua_sum?a=1&b=2

由于该loction是一个内部调用的,外部不能返回,最终返回的结果为404,如下:

<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>openresty/1.11.2.4</center>
</body>
</html>

vim /usr/example/example.conf 添加以下代码:

location = /lua_sum_test {
content_by_lua_block {
local res = ngx.location.capture("/lua_sum", {args={a=3, b=8}})
ngx.say("status:", res.status, " response:", res.body)
}
}

上述的代码通过ngx.location.capture去调用内部的location,并获得返回结果,最终将结果输出,采用curl模拟请求:

$ curl ‘http://116.196.177.123/lua_sum_test

返回结果如下:

status:200 response:11

重定向

vim /usr

location /lua_redirect{
default_type 'text/html';
content_by_lua_file /usr/example/lua/lua_redirect.lua;
}
ngx.redirect("http://www.fangzhipeng.com", 302)

http://116.196.177.123/lua_redirect

共享内存

vim /usr/servers/nginx/cong/nginx.conf

在http模块加上以下:

lua_shared_dict shared_data 1m;
 location /lua_shared_dict{
default_type 'text/html';
content_by_lua_file /usr/example/lua/lua_shared_dict.lua;
}
local shared_data = ngx.shared.shared_data
local i = shared_data:get("i")
if not i then
i = 1
shared_data:set("i",i)
end
i = shared_data:incr("i",1)
ngx.say("i:",i)

多次访问 http://116.196.177.123/lua_shared_dict,浏览器打印:

i:1
i:2
i:3
i:4
i:5

OpenResty执行阶段的概念

以下内容来自于《openresty 最佳实践》

如上图所示,openresty的执行阶段分为

这样我们就可以根据我们的需要,在不同的阶段直接完成大部分典型处理了。

  • set_by_lua* : 流程分支处理判断变量初始化
  • rewrite_by_lua* : 转发、重定向、缓存等功能(例如特定请求代理到外网)
  • access_by_lua* : IP 准入、接口权限等情况集中处理(例如配合 iptable 完成简单防火墙)
  • content_by_lua* : 内容生成
  • header_filter_by_lua* : 响应头部过滤处理(例如添加头部信息)
  • body_filter_by_lua* : 响应体过滤处理(例如完成应答内容统一成大写)

执行阶段概念:

  • log_by_lua* : 会话完成后本地异步完成日志记录(日志可以记录在本地,还可以同步到其 他机器)

    实际上我们只使用其中一个阶段
  • content_by_lua* ,也可以完成所有的处理。但这样做,会让 我们的代码比较臃肿,越到后期越发难以维护。把我们的逻辑放在不同阶段,分工明确,代 码独立,后期发力可以有很多有意思的玩法。




扫码关注公众号有惊喜

(转载本站文章请注明作者和出处 方志朋的博客

Openresty最佳案例 | 第4篇:OpenResty常见的api的更多相关文章

  1. Openresty最佳案例 | 第3篇:Openresty的安装

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616645 本文出自方志朋的博客 我的服务器为一台全新的centos 7的服务器,所以从 ...

  2. Openresty最佳案例 | 第2篇:Lua入门

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616622 本文出自方志朋的博客 什么是lua Lua 是一种轻量小巧的脚本语言,用标准 ...

  3. Openresty最佳案例 | 第9篇:Openresty实现的网关权限控制

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616779 本文出自方志朋的博客 简介 采用openresty 开发出的api网关有很多 ...

  4. Openresty最佳案例 | 第8篇:RBAC介绍、sql和redis模块工具类

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616738 本文出自方志朋的博客 RBAC介绍 RBAC(Role-Based Acce ...

  5. Openresty最佳案例 | 第5篇:http和C_json模块

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616672 本文出自方志朋的博客 http客户端 Openresty没有提供默认的Htt ...

  6. Openresty最佳案例 | 第7篇: 模块开发、OpenResty连接Redis

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616714 本文出自方志朋的博客 Lua模块开发 在实际的开发过程中,不可能把所有的lu ...

  7. Openresty最佳案例 | 第6篇:OpenResty连接Mysql

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616698 本文出自方志朋的博客 centos 安装mysl Centos系统下安装my ...

  8. Openresty最佳案例 | 第1篇:Nginx介绍

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616591 本文出自方志朋的博客 Nginx 简介 Nginx是一个高性能的Web 服务 ...

  9. Openresty最佳案例 | 汇总

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78616856 本文出自方志朋的博客 目录 Openresty最佳案例 | 第1篇:Ngin ...

随机推荐

  1. BNU29139——PvZ once again——————【矩阵快速幂】

    PvZ once again Time Limit: 2000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java cla ...

  2. Java Web SpringMVC AJAX,实现页面懒加载数据

    因为做的微信端的网页,所以在显示后台数据的时候,要么分页,要么全部加载数据,开始分页对于用户来说,其实体验不是很好,毕竟要去不断的点击下一页,但是如果我把全部数据读取出来的话,但用户可能也就看前面几条 ...

  3. 获取top10

    ips = ['', '123.125.71.49', '164.132.161.48', '217.182.132.55', '217.182.132.55', '217.182.132.94', ...

  4. Entity FrameWork利用Database.SqlQuery<T>执行存储过程并返回参数

    目前,EF对存储过程的支持并不完善.存在以下问题: EF不支持存储过程返回多表联合查询的结果集. EF仅支持返回返回某个表的全部字段,以便转换成对应的实体.无法支持返回部分字段的情况. 虽然可以正常导 ...

  5. File 类 的基本操作

    //  File 类(静态类)   File 的缺点:只能用来读小文件 (它是一下子全都读进去) //创建一个文件 // File.Create(@"C:\Users\wbrm\Deskto ...

  6. git把dev部分提交过的内容合并到master

    git 把dev部分提交过的内容合并到master $ git reflog a6de5cc HEAD@{}: checkout: moving from wf_dev to master 303aa ...

  7. 重构指南 - 封装集合(Encapsulate Collection)

    封装就是将相关的方法或者属性抽象成为一个对象. 封装的意义: 对外隐藏内部实现,接口不变,内部实现自由修改. 只返回需要的数据和方法. 提供一种方式防止数据被修改. 更好的代码复用. 当一个类的属性类 ...

  8. win10下MySQL 5.7.20解压版安装步骤

    1.从官网下载MySQL5.7.20解压版64位:https://dev.mysql.com/downloads/file/?id=473309. 2.解压(我的解压路径为:E:\mysql-5.7. ...

  9. 使用git版本管理工具

    1.(1)正常提交:git add 提交文件 git init   //git init之后建立一个.gitignore可以避免node_modules这类文件夹提交 git add . git co ...

  10. 如何将bug杀死在摇篮里?

    阿里妹导读:在欧洲中世纪的传说中,有一种叫“人狼”的妖怪,就是人面狼身.它们会讲人话,专在月圆之夜去袭击人类.而且传说中对“人狼”用一般的枪弹是不起作用的,普通子弹都伤不到也打不死它,只有一种用银子作 ...