OpenResty 最佳实践学习--实战演习笔记(3)

本篇总结来自 OpenResty(Nginx+Lua)开发入门 ,基本的代码没有改动,主要是自己实际动手操作,测试 Nginx Lua API !

我们需要接收请求、处理并输出响应。而对于请求我们需要获取如请求参数、请求头、Body体等信息;而对于处理就是调用相应的Lua代码即可;输出响应需要进行响应状态码、响应头和响应内容体的输出。因此我们从如上几个点出发即可。

接收请求

我自己进行测试,在我安装的openresty目录下的learn_lua新增一个目录,并新增一个request.lua文件

[dufy@localhost learn_lua]$ mkdir req_resp
[dufy@localhost learn_lua]$ cd req_resp
[dufy@localhost req_resp]$ touch request.lua

测试nginx变量

在 nginx.conf 中添加:

# ~ 表示 执行一个正则匹配,区分大小写
# ~*  表示 执行一个正则匹配,不区分大小写 
# (\d+)/(\d+) 匹配数字 ,如 1/2 .
location ~* /lua_request/(\d+)/(\d+) {  
    #设置nginx变量  
    #$1 : 表示获取正则匹配中第一个(\d+)的值,将值赋值给 $a,$a代表一个变量
    set $a $1;   
    #$b 是一个变量,$host 内置变量,获取主机名称
    set $b $host;   
     #$c 是一个变量,$http_host内置变量,获取主机名称
    set $c $http_host;
    default_type "text/html";  
    #nginx使用 lua脚本进行 内容处理  
    content_by_lua_file /usr/example/lua/test_request.lua;  
    #内容体处理完成后调用  
    echo_after_body "ngx.var.b $b";  
    echo_after_body "http_host $c";
}   

在 request.lua 中先添加内容

-- 1.nginx变量  # -- 在lua中代表注释
local var = ngx.var  
ngx.say("ngx.var.a : ", var.a, "<br/>")  
ngx.say("ngx.var.b : ", var.b, "<br/>")  
ngx.say("ngx.var[2] : ", var[2], "<br/>")  
ngx.var.b = 2;  

ngx.say("<br/>")

测试结果如下:

http://192.168.1.110:8080/luA_requesT/1/20

ngx.var.a : 1
ngx.var.b : 192.168.1.110
ngx.var[2]20

ngx.var.b 2 
c var is : 192.168.1.110:8080

[dufy@localhost req_resp]$ curl http://localhost:8080/lua_request/1/110

ngx.var.a : 1<br/>
ngx.var.b : localhost<br/>
ngx.var[2]110<br/>
<br/>
ngx.var.b 2

c var is  : localhost:8080


(1):ngx.var :获取 nginx变量,如果要赋值如ngx.var.b = 2,此变量必须提前声明;
(2):另外对于nginx location中使用正则捕获的捕获组可以使用ngx.var[捕获组数字]获取;

注意:使用ngx.var获取nginx变量,获取的时候是var.a,而不是var.$a,在request_lua中虽然修改 ngx.var.b = 2 ,但是不影响之前的$b变量的值。

测试请求头

nginx.conf 不在做修改,就和上面一样!在 request.lua 中 ,添加下面的代码:

--请求头
--定义一个headers变量
local headers = ngx.req.get_headers()
ngx.say("headers begin :","<br/>");
ngx.say("Host : ",headers["Host"],"<br/>")
--两种方式获取user-agent
ngx.say("user-agent : ",headers["user-agent"],"<br/>")
ngx.say("user-agent : ",headers.user_agent,"<br/>")
--for 循环
ngx.say("---for start---","<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
ngx.say("---for end ---","</br>")
local name = headers.name
ngx.say("name is ",name ,"<br/>")
ngx.say("headers end","<br/>")
ngx.say("<br/>")
-- lua中后面的分号可加可不加,不会报错!

测试结果如下:

http://192.168.1.110:8080/luA_requesT/1/20

headers begin :
Host : 192.168.1.110:8080
user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
---for start---
accept-language : zh-CN,zh;q=0.8
connection : keep-alive
accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
cache-control : no-cache
host : 192.168.1.110:8080
accept-encoding : gzip, deflate
pragma : no-cache
upgrade-insecure-requests : 1
user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
---for end ---
name is :nil  
headers end

这里参数中没有传name,所以name是nil,这个nil类型java中的null,js中的undefined

http://192.168.1.110:8080/luA_requesT/1/20?name=dufy

name is :nil 也是nil,说明ngx.req.get_headers()不能获取uri参数的值,获取的是header中的值。下面看获取uri参数的值。

测试get请求uri参数

nginx.conf 不在做修改,就和上面一样!在 request.lua 中 ,添加下面的代码:

--测试get请求uri参数
ngx.say("get uri args begin ","<br/>")
local uri_args = ngx.req.get_uri_args()
--for循环
ngx.say("headers start","<br/>")
for k,v in pairs(uri_args) do
        if type(v) == "table" then
                ngx.say(k," : ", table.concat(v,","),"<br/>")
        else
                ngx.say(k,":",v,"<br/>")
        end
end
ngx.say("for end","<br/>")
ngx.say("uri args end ","<br/>")

测试结果:

http://192.168.1.110:8080/luA_requesT/1/20?name=dufy&hello=world

get uri args begin 
headers start
hello:world
name:dufy
for end
uri args end 

ngx.req.get_uri_args:获取url请求参数,其用法和get_headers类似!

post请求参数 和其他一些api

nginx.conf 不在做修改,就和上面一样!在 request.lua 中 ,添加下面的代码:

--获取post请求参数
ngx.req.read_body()
ngx.say("post args begin","<br/>")

local post_args = ngx.req.get_post_args()
for k,v in pairs(post_args) do
        if type(v) == "table" then
                ngx.say(k,":",table.concat(v,", "),"<br/>")
        else
                ngx.say(k,": ",v,"<br/>")
        end
end
ngx.say("post args end ","<br/>")

--请求http协议版本
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/>")

测试结果:
使用postman发送post请求,如下截图:

这里写图片描述

ngx.req.http_version : 1.1
ngx.req.get_method : POST
ngx.req.raw_header : POST /luA_requesT/1/20 HTTP/1.1
Host: 192.168.1.110:8080
Connection: keep-alive
Content-Length: 238
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Cache-Control: no-cache
Origin: chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo
X-Postman-Interceptor-Id: 73b998e2-6cad-e3b6-7104-439806d19d25
Content-Type: application/json
Authorization: Basic ZHVmeTo3Mzk0NzU=
Postman-Token: 44e35466-d39a-f2d4-758d-01bb068bbdeb
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8

ngx.req.get_body_data() : ------WebKitFormBoundaryPiqJ6rBwM5pdbAd0
Content-Disposition: form-data; name="name"

dufy
------WebKitFormBoundaryPiqJ6rBwM5pdbAd0
Content-Disposition: form-data; name="date"

20171107
------WebKitFormBoundaryPiqJ6rBwM5pdbAd0--
api参数说明
ngx.varnginx变量,如果要赋值如ngx.var.b = 2,此变量必须提前声明;另外对于nginx location中使用正则捕获的捕获组可以使用ngx.var[捕获组数字]获取;
ngx.req.get_headers获取请求头,默认只获取前100,如果想要获取所以可以调用ngx.req.get_headers(0);获取带中划线的请求头时请使用如headers.user_agent这种方式;如果一个请求头有多个值,则返回的是table;
ngx.req.get_uri_args获取url请求参数,其用法和get_headers类似;
ngx.req.get_post_args获取post请求内容体,其用法和get_headers类似,但是必须提前调用ngx.req.read_body()来读取body体(也可以选择在nginx配置文件使用lua_need_request_body on;开启读取body体,但是官方不推荐);
ngx.req.raw_header未解析的请求头字符串
ngx.req.get_body_data为解析的请求body体内容字符串
ngx.req.get_method“post”或者“get”,详情 http-method-constants

输出响应

api说明
ngx.header输出响应头 ,语法: ngx.header.HEADER = VALUE 或者 VALUE = ngx.header.HEADER
ngx.print输出响应内容体
ngx.say通ngx.print,但是会最后输出一个换行符
ngx.exit指定状态码退出
ngx.redirect重定向

下面进行相应的测试:
nginx.conf 中server添加location:如下:

#測試输出响应的location
    location /lua_response_1{
       default_type "text/html";
       content_by_lua_file learn_lua/req_resp/response_1.lua;
    }

    location /lua_response_2{
       default_type "text/html";
       content_by_lua_file learn_lua/req_resp/response_2.lua;
    }

在learn_lua目录下新增response_1.lua 和 response_2.lua文件 ,内容分别为
response1.lua

-- 测试写响应头
ngx.header.a = "110"
-- 测试多个响应头可以使用table
ngx.header.b = {"120","119"}

ngx.header.learn = "openresty"

-- 测试输出响应
ngx.say("a" , "b" ,"<br/>")
ngx.print("c","d","<br/>")
--200状态码退出
return ngx.exit(200)
--这里可以使用http
-- https://github.com/openresty/lua-nginx-module#http-status-constants
-- ngx.HTTP_OK == 2000
-- return ngx.exit(ngx.HTTP_OK)

response2.lua

--跳转到我的博客地址
ngx.redirect("http://blog.csdn.net/u010648555/article/details/78468364", 302)

response1.lua 测试结果:

http://192.168.1.110:8080/lua_response_1

这里写图片描述

http://192.168.1.110:8080/lua_response_2

response2.lua 测试结果跳转到成功!

其他API

api说明
ngx.escape_uri/ngx.unescape_uriuri编码/解码
ngx.encode_args/ngx.decode_args参数编码/解码
ngx.encode_base64/ngx.decode_base64BASE64编码/解码
ngx.re.matchnginx正则表达式匹配【下面不讲解,详情看文档】

这些api的详细说明可以参考: nginx_modules_lua

nginx.conf 中server添加location:如下:

#测试其他的api
    location /otherapi_test {
        default_type "text/html";
        content_by_lua_file learn_lua/req_resp/otherapi_test.lua;

        echo_after_body "uri = $uri";
        echo_after_body "request_uri = $request_uri";
    }

在learn_lua目录下新增 otherapitest.lua ,内容首先为:

--测试其他的一些API
--ngx.var.request_uri 获取$request_uri Nginx 内建变量的值
--ngx.var.uri  获取$uri内置变量的值
-- $uri,可以用来获取当前请求的 URI(经过解码,并且不含请求参数)
-- $request_uri 则用来获取请求最原始的 URI (未经解码,并且包含请求参数)
-- ngx.escape_uri/ngx.unescape_uri|uri编码/解码
local request_uri = ngx.var.request_uri
local uri = ngx.var.uri
ngx.say("------otherapi_test,lua ouput-------","<p/>")
ngx.say("request_uri :" , request_uri, "<br/>")
ngx.say("uri :" , uri, "<br/>")

--解码
ngx.say("decode request_uri", ngx.unescape_uri(request_uri) ,"<br/>")
--编码
ngx.say("encode  uri", ngx.escape_uri(uri) ,"<br/>")

-- ngx.encode_args/ngx.decode_args|参数编码/解码

local encode_test1 = ngx.encode_args({foo = 3, ["b r"] = "hello world"})

-- encode_test1 : foo=3&b%20r=hello%20world
ngx.say("encode_test1  : " , encode_test1 ,"<br/>")


--MD5  
ngx.say("ngx.md5 : ", ngx.md5("123"), "<br/>")  

测试结果显示如下:

ngx.escape_uri/ngx.unescape_uri|uri编码/解码
http://192.168.1.110:8080/otherapi_test/hello world?name=dufy&age=24

------otherapi_test,lua ouput-------
#未经解码,下面使用ngx.unescape_uri解码!
request_uri :/otherapi_test/hello%20world?name=dufy&age=24
#已经解码,下面使用ngx.escape_uri 编码!
uri :/otherapi_test/hello world
decode request_uri/otherapi_test/hello world?name=dufy&age=24
encode uri%2Fotherapi_test%2Fhello%20world #  %2F == / ; %20 == 空格

#这个是echo_after_body 输出内容
uri = /otherapi_test/hello world 
request_uri = /otherapi_test/hello%20world?name=dufy&age=24

测试参数解码和 MD5 :

http://192.168.1.110:8080/otherapi_test

encode_test1 : foo=3&b%20r=hello%20world
ngx.md5 : 202cb962ac59075b964b07152d234b70


如果您觉得这篇博文对你有帮助,请点个赞,谢谢!


如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!


欢迎访问我的csdn博客,我们一同成长!

不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

博客首页http://blog.csdn.net/u010648555

已标记关键词 清除标记
相关推荐
温铭 王院生  and 13 贡献者 OpenResty最佳实践  开源书籍项目                             --by 温铭  “在2012年的时候,我加入到奇虎360公司,为新的产品做技术选型。由于之前一直混迹在python圈子里面,也接触过nginx c模块的高性能开发,一直想找到一个兼备python快速开发和nginx c模块高性能的产品。看到OpenResty后,有发现新大陆的感觉。 于是我在新产品里面力推OpenResty,团队里面几乎没有人支持,经过几轮性能测试,虽然轻松击败所有的其他方案,但是其他开发人员并不愿意参与到基于OpenResty这个“陌生”框架的开发中来。于是我一个人开始了OpenResty之旅,刚开始经历了各种技术挑战,庆幸有详细的文档,以及春哥和邮件列表里面热情的帮助,我成了团队里面bug最少和几乎不用加班的同学。 2014年,团队进来了一批新鲜血液,他们都很有技术品味,先后都选择OpenResty来作为技术方向。我不再是一个人在战斗,而另外一个新问题摆在团队面前,如何保证大家都能写出高质量的代码,都能对OpenResty有深入的了解?知识的沉淀和升华,成为一个迫在眉睫的问题。 我们选择把这几年的一些浅薄甚至可能是错误的实践,通过gitbook的方式公开出来,一方面有利于团队自身的技术积累,另一方面,也能让更多的高手一起加入,让OpenResty的使用变得更加简单,更多的应用到服务端开发中,毕竟人生苦短,少一些加班,多一些陪家人。 这本书的定位是最佳实践,同时会对OpenResty做简单的基础介绍。但是我们对初学者的建议是,在看书的同时下载并安装OpenResty,把官方网站的Presentations浏览和实践几遍。 希望你能enjoy OpenResty之旅!"
©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页