Nginx添加content_by_lua_block后请求体丢失,求助保留代理并记录请求体
Alright, let's break down what's going on here and get this fixed for you.
The Root Cause
The problem you're hitting is that content_by_lua_block and proxy_pass can't coexist in the same location block—they both operate in Nginx's content processing phase, and only one content-phase directive can run per request. So either your proxy_pass isn't actually executing at all (which explains why your backend is getting an empty body, since the Lua block is handling the request entirely), or the request body is being consumed by Lua and not passed through to the proxy. Either way, we need to shift the Lua logic to an earlier processing phase to avoid conflict.
The Fix: Move Logging to the Access Phase
Instead of using content_by_lua_block, switch to access_by_lua_block. This runs in the access phase, which happens before the content phase where proxy_pass operates. This way, you can log the request body first, then let Nginx proceed with proxying the full request to your backend.
Here's your updated Nginx config:
location /serviceprovider { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; access_by_lua_block{ ngx.req.read_body() local body = ngx.req.get_body_data() -- Add safety checks to avoid errors from empty bodies or file issues if body then local file = io.open("/etc/nginx/test", "w") if file then file:write(body) file:close() end end } }
Why This Works
- Phase Order: Nginx processes requests in a sequence of phases. The
accessphase runs before thecontentphase, so your Lua code will read and write the request body first, then Nginx will seamlessly pass the full request (including the body) toproxy_pass. - Body Preservation:
ngx.req.read_body()just loads the body into memory—it doesn't erase it. As long as you don't modify or discard the body, Nginx will automatically forward it to your backend service. - Error Resilience: I added checks for non-null body data and successful file opening to prevent Lua runtime errors from crashing your request handling (e.g., if a client sends an empty POST or Nginx lacks write permissions for
/etc/nginx/test).
Handling Large Request Bodies
If you expect large request bodies (bigger than client_body_buffer_size), ngx.req.get_body_data() will return nil because Nginx writes large bodies to temporary files instead of memory. For those cases, use this adjusted Lua code to read from the temp file:
access_by_lua_block{ ngx.req.read_body() local body = ngx.req.get_body_data() -- Fall back to temp file if body is too big for buffer if not body then local temp_file = ngx.req.get_body_file() if temp_file then local f = io.open(temp_file, "r") body = f:read("*a") f:close() end end -- Write to your log file if we have body content if body then local file = io.open("/etc/nginx/test", "w") if file then file:write(body) file:close() end end }
Quick Permission Note
Make sure the Nginx process (usually running as nginx or www-data user) has write permissions for /etc/nginx/test. If not, you'll get silent failures when trying to write the file—you can fix this with chown nginx:nginx /etc/nginx/test or pick a different path that's writable.
内容的提问来源于stack exchange,提问作者Joshgun

