ngx_lua POST request body reading issues

1,940 views
Skip to first unread message

Kipras Mancevičius

unread,
May 14, 2015, 12:54:42 PM5/14/15
to openre...@googlegroups.com
Hey,

i'm having issues trying to proxy POST requests with ngx_lua.
I'm using https://github.com/pintsized/lua-resty-http to run the actual requests to upstream.

The problem is with request body reading.
The default (and afaik most efficient) way to do this is to use the lua-resty-http get_client_body_reader() function. But this doesn't work when under an HTTPS SPDY connection, because it uses ngx.req.socket() to read the request body (which doesn't work under SPDY).

So in that case we can fall back to using ngx.req.get_body_data(), but now we face an issue when POST data size exceeds client_body_buffer_size, and the response data is now buffered into temporary files and this method returns nil.

So then you can then call ngx.req.get_body_file() to get the temporary file name, which it does return. However, trying to read the file gives an error like this:
 
error while opening file: /usr/local/openresty/nginx/client_body_temp/0000000100: No such file or directory

Which makes no sense, considering that ngx.req.get_body_file() did return this file path, which means it is actually used. It probably gets deleted before you can try to access it.

One workaround is to set client_body_in_file_only to "on" or "clean" in nginx config, in which case you can actually read that file and forward the request body stored in it. But i fear this may have performance implications, since afaik all POST requests bodies (even small ones) will now be buffered to disk.

Is anyone aware of these issues, and if so - do you know of any stable, recommended way of dealing with POST request bodies?

Kipras Mancevičius

unread,
May 15, 2015, 5:49:54 AM5/15/15
to openre...@googlegroups.com
Turns out the issue (not being able to open the temporary request body file) was caused by calling ngx.req.get_post_args() after ngx.req.read_body(). When ngx.req.get_post_args() is not called - everything works well.

Seems like a bug in ngx_lua or perhaps some info missing from documentation?

nginx version: openresty/1.7.4.1

Kipras Mancevičius

unread,
May 15, 2015, 6:08:38 AM5/15/15
to openre...@googlegroups.com
ok, so i get this error when calling ngx.req.get_post_args() for POST requests with a large body size (> 16kb):

requesty body in temp file not supported

So i guess, this is probably expected behavior for the current ngx_lua, and in this case (when request body is in a temp file) you have to parse POST arguments yourself in Lua, right?

Suggestion: adding some quick notice about this in the docs (for the ngx.req.get_post_args()) would help, i think :)

Hamish Forbes

unread,
May 15, 2015, 7:22:40 AM5/15/15
to openre...@googlegroups.com

You could try proxying the https SPDY connections to a non-SPDY endpoint (e.g. an alternate port on localhost) and then use lua-resty-http and get_client_body_reader() to stream the request to your upstream from there.
Our architecture has a vanilla Nginx proxy terminating SPDY/TLS in front of any systems running Lua anyway so we haven't had this problem.
That approach still buffers the whole request on the SPDY/Nginx proxy before its streamed through to your resty-http and upstream though.
Does anyone know if http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_request_buffering works with SPDY? As that would resolve that problem.

Alternatively I think you should be able to write a wrapper that uses ngx.req.get_body_file() and reads the buffered file (in chunks) and passes them through to lua-resty-http.
As long as your function returns data in chunks until its done, then returns nil it should just drop in.
Still have to let Nginx buffer the request to disk first though.

Kipras Mancevičius

unread,
May 15, 2015, 9:49:32 AM5/15/15
to openre...@googlegroups.com


Alternatively I think you should be able to write a wrapper that uses ngx.req.get_body_file() and reads the buffered file (in chunks) and passes them through to lua-resty-http.

Yes, that's what i did. Works just fine in simple tests but i still have yet to stress test it.
Reply all
Reply to author
Forward
0 new messages