nginx 记录完整的 request 及 response

前言

在开发的过程中, 经常会有抓包的需求, 查看请求体和响应体. 使用 charles 等抓包工具会遇到一些麻烦, 如:

  1. localhost 请求无法捕获
  2. 有些工具配置代理比较麻烦, 如docker配置代理后需要重启
  3. https协议需要代理端配置证书进行解密, 比较麻烦

于是, 我就在想, 能否直接在服务端将所有的请求体和响应体打印出来, 不就完美解决这个问题了么?

一般来说, 通过nginx代理请求, 所有的请求都过nginx, nginx自身也有https的私钥, 会进行解密.

那么问题来了, 如何通过nginx打印请求呢?

中间探索的过程就不提了, 直接上结果.

lua打印

这里直接使用openresty/openresty镜像了, 当然如果直接使用nginx编译lua插件也是可以的.

在配置文件中添加如下lua脚本以打印完整请求内容:

# 将请求信息暂存, 放到最后一起打印
access_by_lua_block {
  ngx.req.read_body()
  local req_body = ngx.req.get_body_data()
  local req_uri = ngx.var.request_uri
  local req_method = ngx.var.request_method
  if req_body and #req_body > 1024 * 1024 then
    req_body = "Request too large"
  end
  if not req_body then
    req_body = "No request body"
  end
  local headers = ngx.req.get_headers()
  local header_str = ""
  for k, v in pairs(headers) do
    header_str = header_str .. string.format("%s: %s\n", k, v)
  end
  ngx.ctx.req_info = {
    uri = req_uri,
    body = req_body,
    method = req_method,
    headers = header_str
  }
}

body_filter_by_lua_block {
  local req_info = ngx.ctx.req_info or {}
    local req_uri = req_info.uri or "Unknown URI"
    local req_body = req_info.body or "Unknown Request Body"
    local req_method = req_info.method or "Unknown Method"
    local req_headers = req_info.headers or "Unknown Headers"
    local resp_headers = ngx.resp.get_headers()
    local resp_header_str = ""
    for k, v in pairs(resp_headers) do
        resp_header_str = resp_header_str .. string.format("%s: %s\n", k, v)
    end

    if ngx.ctx.buffered_resp_body == nil then
        ngx.ctx.buffered_resp_body = ""
        ngx.ctx.buffered_resp_size = 0
    end

    local current_chunk = ngx.arg[1] or ""
    ngx.ctx.buffered_resp_body = ngx.ctx.buffered_resp_body .. current_chunk
    ngx.ctx.buffered_resp_size = ngx.ctx.buffered_resp_size + #current_chunk

    if ngx.ctx.buffered_resp_size > 1024 * 1024 then
        ngx.ctx.buffered_resp_body = "Response body too large to log"
    end
    if ngx.arg[2] then
        ngx.log(ngx.ERR, string.format(
            "Request Method: %s\nRequest URI: %s\nRequest Headers:\n%sRequest Body: %s\nResponse Headers:\n%sResponse Body: %s\n",
            req_method,
            req_uri,
            req_headers,
            req_body,
            resp_header_str,
            ngx.ctx.buffered_resp_body
        ))
    end
}

这段逻辑在location中.

完整内容可参考: https://github.com/hujingnb/docker_composer/tree/master/openresty

简单记录一下, 以方便后续获取请求使用

posted @   烟草的香味  阅读(195)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
历史上的今天:
2019-12-15 网络带宽是什么
点击右上角即可分享
微信分享提示
主题色彩