Reputation: 9484
I'm experimenting with the Nginx Lua module. Currently, my goal is simply to save certain HTTP responses to a local file on disk.
After reading a few tutorials, my understanding is that I can do this using the body_filter_by_lua
directive. My approach is simply to embed some Lua code in the nginx.conf
file, retrieve the response body from ngx.arg
, and then use standard Lua io
facilities to write it to disk.
I have never programmed in Lua before, but I've programmed extensively in other scripting languages like Python, so I found it fairly easy to learn the basics of Lua.
Still, my approach isn't working, and the nginx error.log
indicates the problem is that the file
object I open is nil
.
Here is the Lua code I place inside the nginx.conf
file (edited for clarity):
location /foo {
proxy_pass http://my_upstream_proxy;
proxy_cache my_cache;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
body_filter_by_lua '
local resp_body = ngx.arg[1]
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
if ngx.arg[2] then
ngx.var.resp_body = ngx.ctx.buffered
end
local file = io.open("TEST.txt", "w+b")
file:write(resp_body)
file:close()
';
}
So the idea here is that nginx would simply pass the request on to a proxy, and then write the response body out to a local file.
I test this using:
curl http://www.google.com --proxy http://localhost:80
But nginx returns an empty reply.
So I check the error log and see:
2016/12/15 11:51:00 [error] 10056#0: *1 failed to run body_filter_by_lua*: body_filter_by_lua:9: attempt to index local 'file' (a nil value)
stack traceback:
body_filter_by_lua:9: in function <body_filter_by_lua:1> while sending to client, client: 127.0.0.1, server: test-server, request: "GET http://www.google.com/ HTTP/1.1", upstream: "http://69.187.22.138:82/", host: "www.google.com"
So why is my local file
variable nil
? When I open up a Lua console using bash, I am able to open/create a new local file and write text to it without any issues.
So what am I doing wrong? At first I thought it might be some permissions issue and nginx is unable to write a file in the current working directory, but it's my understanding that nginx
runs as root. I tried an absolute path like /home/myusername/NGINX.txt
, and it still fails with a nil
file. I'm not able to get a more specific error about why file
is nil
.
So what am I doing wrong?
Upvotes: 4
Views: 10271
Reputation: 271
io.open will return nil if it was unable to open the file. You can retrieve the error message:
local file, err = io.open("TEST.txt", "w+b")
if file == nil then
print("Couldn't open file: " .. err)
else
file:write(resp_body)
file:close()
end
Upvotes: 5
Reputation: 11
Permission issue. No right to create/open "test.txt" there. As for me, /usr/local/nginx-1.14.2/sbin/
Solution: grant permission. in my test env., /usr/local/nginx-1.14.2/ sudo chomd -r 777
To find what real issue is, try this below, to replace your "io.open" part
handle_name, err = io.open(file,"w")
print(err)
I got "permission denied" error msg with lua statments above.
Upvotes: 1
Reputation: 481
I think you should change:
local file = io.open("TEST.txt", "w+b")
To:
local file = io.open("TEST.txt", "a")
Upvotes: 0
Reputation: 12775
Not an expert on Lua but in my dabling, I picked up somewhere to wrap "io.open" calls in an "assert" function. See docs on assert
local file = assert(io.open("TEST.txt", "w+b"), "Inaccessible file")
This will probably just confirm that this is where the code is failing. Looking at that line, I am not sure what the "b" mode is in "w+b".
Did you mean to overwrite as in io.open("TEST.txt", "w")
or, append as in io.open("TEST.txt", "a")
?
If you test with these and still get an error, then it means the file is actually not being accessed.
Upvotes: 0