1. 程式人生 > >OpenResty body_filter_by_lua Nginx 指定返回內容

OpenResty body_filter_by_lua Nginx 指定返回內容

背景:

需要統一處理error的返回,其實呢就是nginx 預設的error 會是html格式,而且返回的不符合我們統一規範,所以需要在最後歸一化。 當然也可以延伸到 在body_filter_by_lua中 修改返回內容,甚至指定返回內容

原理說明:

首先需要先宣告!!HTTP1.1 之後基於流式處理的方式,body_filter_by_lua 基本在一個請求中會呼叫多次。 簡單直白的理解就是流式輸出,每次拿到了如果你要處理那麼就處理,不處理就輸出!!

The input data chunk is passed via ngx.arg[1] (as a Lua string value) and the "eof" flag indicating the end of the response body data stream is passed via 

ngx.arg[2] (as a Lua boolean value).

簡單說明就是

流每次的內容輸出在ngx.arg[1]  中; 是否到eof -最後 的標記在ngx.arg[2] 中

所以你要改輸出內容 那麼就把ngx.arg[1]  改掉,如果不想要以後的內容了那麼ngx.arg[2]=true 就行

程式碼:

body_filter.lua
---
--- Created by sunfangyuan.
--- DateTime: 18/1/31 上午9:53
---
local headers = ngx.header
local constant = require("conf.constant")
local log = ngx.log
local ERR = ngx.ERR
local json_util = require("cjosn")

local function res_json()
    local res = {}
    res["message"] = "你希望輸出的內容"
    res["code"] = "你希望輸出的內容"
    return json_util.encode(res)
end

if headers["Content-Type"] == nil or string.find(headers["Content-Type"], "application/json") == nil then
    local status = ngx.var.status
    headers["Content-Type"] = "application/json"
    local chunk, eof = ngx.arg[1], ngx.arg[2]  -- 獲取當前的流 和是否時結束
    local info = ngx.ctx.buf
    chunk = chunk or ""
    if info then
        ngx.ctx.buf = info .. chunk -- 這個可以將原本的內容記錄下來
    else
        ngx.ctx.buf = chunk
    end
    if eof then
        ngx.ctx.buffered = nil
        if status == 413 or status == "413" then  -- 413是nginx request body 超過限制時的狀態嗎
            ngx.arg[1] = res_json() -- 這個是你期待輸出的內容
        else
            log(ERR, "[ Internal Exception ] " .. ngx.ctx.buf)
            ngx.arg[1] = res_json()
        end
    else
        ngx.arg[1] = nil -- 這裡是為了將原本的輸出不顯示
    end
end

由於改變了body內容長度,記得更新header 裡的長度

ngx.header.content_length = nil