nginx OpenResty lua resty http 代理網關從無到有搭建

一、背景說明
準備在項目中基於nginx、OpenResty搭建一個簡易網關,實現同一域名根據不同cookie代理不同docker功能,降低前端、移動端多業務線並行測試聯調成本。簡單來說就是服務端有多個測試環境docker分別部署不同業務需求代碼,通過在前端、移動端種植cookie(存放服務端測試環境docker IP地址)方式讓其具有可選擇服務端測試環境能力,大大降低聯調環境配置成本。具體cookie的解析邏輯在nginx中使用lua實現。

二、lua中讀寫header、cookie 代碼

---獲取請求header
local reqHeaders = ngx.req.get_headers();
---獲取請求cookie
local reqCookie = reqHeaders["cookie"];
--讀取cookie值
local pcip = ngx.var.cookie_pcip;
pcip=reqCookie["pcip"];
--設置賦值cookie
ngx.header['Set-Cookie']={"pcip=127.0.0.1;domain=.timer.com;path=/" }

注:在nginx.header['Set-Cookie'] 時遇到一個問題,一次性種植多個cookie時,會出現無法一次性全部種植成功的情況,需要多次請求種植方能全部種植成功,在實戰中請慎用。尤其在ngx.say()方法調用之前種植cookie出現無法一次種植成功現象機率大,在ngx.print()方法調用之前種植cookie也會如此。
其他輔助代碼:

--獲取請求URI
local requestUri = ngx.var.request_uri;
--獲取請求域名
local requestHost = ngx.var.host;
----獲取請求方法類型GET POST
local reqType= ngx.var.request_method;
--打印日誌
ngx.log(ngx.ERR, ',requestHost:'..requestHost);
--反饋客戶端信息
ngx.print("反饋輸出純文本");
ngx.say("反饋輸出頁面");

三、lua 腳本中嵌入 resty.http 文件,在lua中藉助於resty.http代理http請求
resty.http (http.lua和http_headers.lua)文件下載地址:https://github.com/ledgetech/lua-resty-http/tree/master/lib/resty

--引入resty.http文件
package.path = package.path..';/export/Instances/timer/lua/resty/?.lua;'
local myHttp = require "http"
---Get 請求
local function http_get(url,headerParm,timeout)
    local httpc = myHttp.new();
    timeout = timeout or 30000;
    httpc:set_timeout(timeout)
    local res, err_ = httpc:request_uri(url, {
        method = "GET",
        keepalive=false,
        headers = headerParm;
    })
    httpc:set_keepalive(5000, 100);
    ---httpc:close();
    return res,err_;
end
---Post 請求
local function http_post(url,headerParm,body,timeout)
    local httpc = myHttp.new();
    timeout = timeout or 30000;
    httpc:set_timeout(timeout);
    local res, err_ = httpc:request_uri(url, {
        method = "POST",
        body = body,
        keepalive=false,
        headers =  headerParm;
    })
    httpc:set_keepalive(5000, 100)
    ---httpc:close();
    return res,err_;
end

在lua腳本中根據請求類型代理Http請求:

---請求路徑
local reqUrl ="代理的請求URL地址";
----請求類型
local reqType= ngx.var.request_method;
--讀取reqResult返回結果中的header 信息,賦值給nginx的Response header中
local function setResHeader(res)
    if(res ~= nil)then
        for k,v in pairs(res.headers) do
            ngx.header[k]=v;
        end
    end
end

if reqType == 'POST' then
    ngx.req.read_body();
    local reqBody = ngx.req.get_body_data();
    local reqResult,reqErr = http_post(reqUrl,reqHeaders,reqBody,30000);
    ngx.status = reqResult.status;
    setResHeader(reqResult);
    if(reqResult.status==200) then
        --返回200 code碼時直接將結果返回
        ngx.say(reqResult.body);
        return ;
    elseif(reqResult.status==302) then
        --返回302 重定向時 需要將重定向url 賦值到response 的header.Location中
        ngx.header.Location=reqResult.headers.location;
        return ;
    else
        --報錯處理
        if reqErr == nil then
            reqErr="";
        end
        ngx.say(reqResult.status..":"..reqErr);
        return ;
    end
else
    local reqResult,reqErr = http_get(reqUrl,reqHeaders,30000);
    ngx.status = reqResult.status;
    setResHeader(reqResult);
    if(reqResult.status==200) then
        ngx.say(reqResult.body);
        return ;
    elseif(reqResult.status==302) then
        ngx.header.Location=reqResult.headers.location;
        return ;
    else
        if reqErr == nil then
            reqErr="";
        end
        ngx.say(reqResult.status..":"..reqErr);
        return ;
    end
end

四、nginx 引入lua腳本

server {
    listen          80;
    server_name     www.timer.com;
    access_log      /export/servers/nginx/logs/nginx_access.log realaddr;
    error_log       /export/Logs/nginx_errr.log warn;
	
    root /export/Instances/timer/runtime/;
  
    index index.html;
    charset utf-8;
	
    location / {
	  #default_type 'text/html';   返回HTML頁面
      default_type 'application/json'; #返回Json文本
      charset utf-8;  
      lua_code_cache off;
      #加載引入lua腳本
      content_by_lua_file /export/Instances/timer/runtime/lua/gateway.lua;
    }
}

注:使用access_by_lua_file加載lua腳本會出現間接性404問題:https://blog.csdn.net/TimerBin/article/details/103850392
五、其他資料
resty-http幫助文檔: https://github.com/ledgetech/lua-resty-http#request

發佈了109 篇原創文章 · 獲贊 16 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章