Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing to a file using Nginx Lua module

Tags:

http

nginx

lua

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?

like image 640
Siler Avatar asked Oct 15 '25 04:10

Siler


2 Answers

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
like image 178
Pobtastic Avatar answered Oct 16 '25 17:10

Pobtastic


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.

like image 26
daggerin Avatar answered Oct 16 '25 16:10

daggerin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!