1. 程式人生 > >OpenResty 最佳實踐學習--實戰演習筆記(3)

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/>")

測試結果如下:

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
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中後面的分號可加可不加,不會報錯!

測試結果如下:

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

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/>")

測試結果:

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.var nginx變數,如果要賦值如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

輸出響應

api 說明
輸出響應頭 ,語法: ngx.header.HEADER = VALUE 或者 VALUE = ngx.header.HEADER
ngx.print 輸出響應內容體
ngx.say 通ngx.print,但是會最後輸出一個換行符

下面進行相應的測試:
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測試結果:

這裡寫圖片描述

response2.lua測試結果跳轉到成功!

其他API

api 說明
ngx.escape_uri/ngx.unescape_uri uri編碼/解碼
ngx.encode_args/ngx.decode_args 引數編碼/解碼
ngx.encode_base64/ngx.decode_base64 BASE64編碼/解碼
nginx正則表示式匹配【下面不講解,詳情看文件】

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/>")  

測試結果顯示如下:

------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 :

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


如果您覺得這篇博文對你有幫助,請點個贊,謝謝!


如果帥氣(美麗)、睿智(聰穎),和我一樣簡單善良的你看到本篇博文中存在問題,請指出,我虛心接受你讓我成長的批評,謝謝閱讀!
祝你今天開心愉快!

歡迎訪問我的csdn部落格,我們一同成長!

不管做什麼,只要堅持下去就會看到不一樣!在路上,不卑不亢!