我想在代理请求的同时 来记录用户的接口调用日志 以下为相关代码 使用时发现 $resp_body 长度只有 3744 实际上返回有2万多个字符,我如何才能得到完整的响应内容,内容长度 1mb 也是可能的
location /api/ {
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, DELETE, PUT, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, X-Custom-Header, Access-Control-Expose-Headers, Token, Authorization,Appalias';
add_header 'Access-Control-Max-Age' 1728000;
if ($request_method = 'OPTIONS') {
return 204;
}
set $resp_body "";
body_filter_by_lua '
local resp_body = string.sub(ngx.arg[1], 1, 1000)
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
if ngx.arg[2] then
ngx.var.resp_body = ngx.ctx.buffered
end
';
log_by_lua_file mylua/log.lua;
proxy_pass http://localhost:204;
}
以下为log.lua的内容
local json = require "cjson.safe"
local http = require "resty.http"
local function record_visit_data(premature, record)
if not premature then
ngx.log(ngx.ERR, "发出了请求,请求参数是");
ngx.log(ngx.ERR, json.encode(record));
-- 如果是登录接口 调另一个接口保存 record
local httpc = http.new()
local res, err = httpc:request_uri('http://192.168.1.167:204/api/Operation/AutoLog', {
headers = {
["Content-Type"] = "application/json;charset=UTF-8",
["token"] = record.token,
},
method = "POST",
keepalive_timeout = 2000, -- 毫秒
body = json.encode(record)
})
if (not res) or (res.status == 502) then
if not res then
ngx.log(ngx.ERR, "请求出错#", err)
else
ngx.log(ngx.ERR, "请求出错 header status=502")
end
else
--ngx.log(ngx.ERR, '更新结果', res.body)
local json_data = json.decode(res.body).data
return json_data
end
end
end
--split来源 https://blog.csdn.net/heyuchang666/article/details/52403087
local function split(input, delimiter)
input = tostring(input)
delimiter = tostring(delimiter)
if (delimiter=='') then return false end
local pos,arr = 0, {}
-- for each divider found
for st,sp in function() return string.find(input, delimiter, pos, true) end do
table.insert(arr, string.sub(input, pos, st - 1))
pos = sp + 1
end
table.insert(arr, string.sub(input, pos))
return arr
end
-- ngx.log(ngx.ERR, "进入了日志记录111");
-- ngx.print("进入了日志记录111\r\n")
local ua = ngx.ctx.ua;
local request_method = ngx.var.request_method
local req_method
local req_param
local req_body = "";
if request_method == 'GET' then
req_method = 0
req_param = ngx.var.args
elseif request_method == 'POST' then
req_method = 1
req_param = ngx.var.args
req_body = ngx.req.get_body_data()
elseif request_method == 'PUT' then
req_method = 2
elseif request_method == 'DELETE' then
req_method = 3
elseif request_method == 'OPTION' then
req_method = 4
else
req_method = 5
end
if(req_method > 3)
then
return;
end
local tmp = (string.gsub(ngx.var.uri, "?.*", ""))
tmp = string.lower(tmp)
tmp = (string.gsub(tmp, '/api/', ""))
--ngx.ctx.buf
local rexponseData = ngx.var.resp_body;
local res = split(tmp, "/")
-- res 长度为2 且 第二个参数 要有关键字 update create add delete discard 时才进行记录 暂不区分
--第二个参数不是login 时进行记录 (暂采用这种)
-- 返回状态不是200时 (可能原因有用户未登录,系统内部错误, 调用一个不用鉴别用户身份的接口进行记录)
if((res[2] == "login") or (res[2] == "islogined" ))
then
return;
end
-- local ua = ngx.ctx.ua;
local record = {
ControllerName = res[1],
ActionName = res[2],
url = ngx.var.uri,
req_method = request_method,
query = req_param,
body = req_body,
ip = ngx.var.remote_addr,
ua = ngx.var.http_user_agent,
referer = ngx.var.http_referer,
response = rexponseData,
-- browser = ua.name,
-- browser_platform = ua.category,
-- browser_version = ua.version,
-- browser_vendor = ua.vendor,
-- os = ua.os,
-- os_version = ua.os_version,
status = ngx.status,
CostTime = ngx.now() - ngx.req.start_time(),
post_id = ngx.ctx.post_id,
search_stat = ngx.ctx.search_stat,
is_mini_program = ngx.ctx.is_mini_program,
token= ngx.req.get_headers()["token"],
AppName = ""--这里应通过配置内的局部变量来搞定 方便多个站点使用
}
local ok, err = ngx.timer.at(0, record_visit_data, record)
if not ok then
ngx.log(ngx.ERR, "failed to create record_visit_data timer#", json.encode(record), ", err#", err)
return
end