Hey,
So I have it about 80% of the way there (thanks for all your help!). I foreach over the headers and send them upstream to our node.js app, however, i'm curious if a header is repeated (ie Set-Cookie) how to check for such a case.
Also, when the Node.js app responds, because it is a TCP socket, it sends all the normal HTTP headers with it. however, ngx.print() will attempt to send headers for me. Is there a way to write to the ngx socket (ie ngx.say(), ngx.print()) without it first sending headers on my behalf? Ideally, i would like ngx.print to stream the data as it comes in from the node.js app, without trying to do any HTTP parsing logic.
Thanks again,
dave
ps: here is the content_by_lua portion I have currently
-- connect to node
local node_sock, err = ngx.socket.connect("127.0.0.1", 8080)
if err then
ngx.say("failed to connect to node: ", err)
return
end
-- get the req.socket
local req_sock, err = ngx.req.socket()
if not req_sock then
ngx.say("failed to connect to req.socket: ", err)
return
end
-- send the request to node
local method = ngx.req.get_method()
node_sock:send(method .. " " .. ngx.var.uri .. " " .. "HTTP/1.1\\r\\n")
-- headers
local h = ngx.req.get_headers()
for k, v in pairs(h) do
node_sock:send(k .. ": " .. v .. "\\r\\n")
end
node_sock:send("X-Forwarded-For: nginx\\r\\n")
-- body
if method == "POST" or method == "PUT" then
while true do
local line, err, partial = req_sock:receive();
if err then
if partial then
node_sock:send(partial)
end
break;
end
node_sock:send(line);
end
node_sock:send("\\r\\n")
end
node_sock:send("\\r\\n")
-- receive the response
while true do
local line, err, partial = node_sock:receive();
if err then
if partial then
ngx.print(partial)
ngx.flush(true)
end
break;
end
ngx.print(line)
ngx.flush(true)
end
-- close the node socket (??)
ngx.req.finish_body()
node_sock:close()
On Tue, Oct 2, 2012 at 2:34 PM, agentzh
<age...@gmail.com> wrote:
Hello!
On Tue, Oct 2, 2012 at 2:05 PM, Dave Eddy wrote:
> However, i realized my mistake instantly, that the data provided by
> ngx.req.socket():receive is just the POST data, and not all of the headers
> (which makes sense). I'm thinking I will need to add in logic to
> reconstruct the headers before forwarding to Node.js, adding in
> X-Forwarded-For, etc.
>
Yes. Check out the ngx.req.get_headers() API provided by ngx_lua:
http://wiki.nginx.org/HttpLuaModule#ngx.req.get_headers
Also, you'll need to receive the TCP response from your upstream
servers (i.e., your nodejs app in this case) and forward the data
chunk to the downstream. (Check out the ngx.print and ngx.flush
functions provided by ngx_lua.)
Essentially, you're just coding up a nonbuffered HTTP proxy in pure
Lua running inside Nginx ;)
> Is this the right approach to tackle this problem? or am I thinking about
> this wrong.
>
This approach should work. To maximize the performance, you may want
to consider migrating all your nodejs app code right over to ngx_lua
(if possible) ;)
Best regards,
-agentzh