V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
dunhanson
V2EX  ›  程序员

openresty 如何正确修改响应内容?

  •  
  •   dunhanson · 47 天前 · 1214 次点击
    这是一个创建于 47 天前的主题,其中的信息可能已经有所发展或是发生改变。

    zlib 解压内容正常,但是压缩后就不正常,页面无法展示

    -- body_filter_by_lua_file test.lua
    if ngx.header.content_encoding:lower() == "gzip" then
        local res, eof = ngx.arg[1], ngx.arg[2]
        local zlib = require "zlib"
        -- 解压
        res = zlib.inflate()(res)
        ngx.log(ngx.INFO, 'inflate res:'..res)
        -- 替换
        res = string.gsub(res, 'aaa', 'bbb')
        -- 压缩
        res = zlib.deflate()(res, 'sync')
        ngx.log(ngx.INFO, 'deflate res:'..res)
        ngx.arg[1] = res
    end
    
    第 1 条附言  ·  47 天前

    2024-11-09 14:23:00 找了一种新方式也是有问题

    local zlib = require('ffi-zlib')
    if ngx.header.content_encoding:lower() == "gzip" then
        -- 解压
        local decompressed
        local ok, err = zlib.inflateGzip(function()
            return ngx.arg[1]
        end, function(data)
            decompressed = data
        end)
        if ok then
            ngx.log(ngx.INFO, 'decompressed:'..decompressed)
            -- 压缩
            local compressed
            ok, err = zlib.deflateGzip(function()
                return decompressed
            end, function(data)
                compressed = data
            end)
            if ok then
                ngx.log(ngx.INFO, 'compressed:'..compressed)
                ngx.arg[1] = compressed
                ngx.header["Content-Length"] = string.len(res)
            end
        end
    end
    
    第 2 条附言  ·  47 天前

    2024-11-09 15:26:00 也还是有问题

    -- body_filter_by_lua_file:
    -- 获取当前响应数据
    local chunk, eof = ngx.arg[1], ngx.arg[2]
    
    -- 定义全局变量,收集全部响应
    if ngx.ctx.buffered == nil then
        ngx.ctx.buffered = {}
    end
    
    -- 如果非最后一次响应,将当前响应赋值
    if chunk ~= "" and not ngx.is_subrequest then
        table.insert(ngx.ctx.buffered, chunk)
    
        -- 将当前响应赋值为空,以修改后的内容作为最终响应
        ngx.arg[1] = nil
    end
    
    -- 如果为最后一次响应,对所有响应数据进行处理
    if eof then
        -- 获取所有响应数据
        local whole = table.concat(ngx.ctx.buffered)
        ngx.ctx.buffered = nil
    
        -- 进行你所需要进行的处理
        local zlib = require "zlib"
        whole = zlib.inflate()(whole)
        ngx.log(ngx.INFO, 'inflate whole:'..whole)
        whole = zlib.deflate()(whole, 'full')
        ngx.log(ngx.INFO, 'deflate whole:'..whole)
        
        -- 重新赋值响应数据,以修改后的内容作为最终响应
        ngx.arg[1] = whole
    end
    
    第 3 条附言  ·  47 天前

    我搞定了

    header_filter.lua

    -- ngx.header["Content-Encoding"] = 'deflate'
    ngx.header["Content-Encoding"] = ''
    

    body_filter.lua

    -- body_filter_by_lua_file:
    -- 获取当前响应数据
    local chunk, eof = ngx.arg[1], ngx.arg[2]
    
    -- 定义全局变量,收集全部响应
    if ngx.ctx.buffered == nil then
        ngx.ctx.buffered = {}
    end
    
    -- 如果非最后一次响应,将当前响应赋值
    if chunk ~= "" and not ngx.is_subrequest then
        table.insert(ngx.ctx.buffered, chunk)
    
        -- 将当前响应赋值为空,以修改后的内容作为最终响应
        ngx.arg[1] = nil
    end
    
    -- 如果为最后一次响应,对所有响应数据进行处理
    if eof then
        -- 获取所有响应数据
        local whole = table.concat(ngx.ctx.buffered)
        ngx.ctx.buffered = nil
    
        -- 进行你所需要进行的处理
        local zlib = require "zlib"
        whole = zlib.inflate()(whole)
        ngx.log(ngx.INFO, 'inflate whole:'..whole)
        -- 重新压缩
        -- whole = zlib.deflate()(whole, 'finish')
        -- ngx.log(ngx.INFO, 'deflate whole:'..whole)
        
        -- 重新赋值响应数据,以修改后的内容作为最终响应
        ngx.arg[1] = whole
    end
    
    6 条回复    2024-11-09 14:00:48 +08:00
    dunhanson
        1
    dunhanson  
    OP
       47 天前
    有没有大佬知道?
    moen
        2
    moen  
       47 天前
    更改内容后可能会对不上 Content-Length ,需要在 header_filter 把这个 header 去掉。openresty 文档有提及过这点
    dusu
        3
    dusu  
       47 天前 via iPhone
    不仅 length 要重置
    返回的 header 要不丢掉 gzip 头 要不也要 gzip 数据
    joyoyao
        4
    joyoyao  
       47 天前
    ngx.header.content_length = nil
    -- in case of upstream content is compressed content
    ngx.header.content_encoding = nil

    -- clear cache identifier
    ngx.header.last_modified = nil
    ngx.header.etag = nil

    还有个简单的方法,请求的时候就不要压缩,更改 accept-encoding: 设置空,请求过来的数据直接是明文,方便更改。
    dunhanson
        5
    dunhanson  
    OP
       47 天前
    @moen 我用原文压缩也是一样
    dunhanson
        6
    dunhanson  
    OP
       47 天前
    @joyoyao 按你写的也是有问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3395 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 11:14 · PVG 19:14 · LAX 03:14 · JFK 06:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.