Hello!
On Wed, Jul 15, 2015 at 2:46 AM, Stefan Wille wrote:
> We have an OpenResty server that proxies a backend server. The backend
> server normally sends HTML, images etc. but we would like to be also able to
> retrieve Lua code from the backend server and execute it in OpenResty.
[...]
> The approach we favor is to set an HTTP response header on the backend
> server to indicate that the response body contains Lua code. Then we want
> Nginx to react to the response header, execute the Lua code and then replace
> the response with the result. Is this possible? How can we let OpenResty
> react to response headers and replace the response body?
>
Hmm, very strange requirement. You seem to be following the PHP style,
which is *inherently* inefficient without code caching. Be careful.
Having said that, you could implement some kind of a Lua code cache.
Basically, while loading the Lua code from string in case of a cache
miss:
local lua_code = ...
local checksum = ngx.md5(lua_code)
local chunk = loadstring(lua_code, "my chunk name")
my_global_code_cache[checksum] = chunk
For normal code path, always look up the cache first:
local chunk = my_global_code_cache["my-module-name"]
if chunk then
-- cache hit! now execute it right away
chunk()
else
-- cache miss, use the code snippet above to load it from string!
end
Here we use a plain Lua table to illustrate the idea, which is not
very good in practice because this "my_global_code_cache" table MAY
grow forever and result in a memory leak over time. So you should
really use the lua-resty-lrucache library for a fixed-size LRU-enabled
cache implementation.
For detecting, receiving, evaluating, and replacing the response body,
you can use the body_filter_by_lua* directive.
> What also came to our minds is a solution that we know from Varnish: The
> first few bytes of every resource are read and based on that Varnish
> distinguishes text from binary files. We could use something similar to
> detect Lua.
>
Well, you can surely do that. body_filter_by_lua* is based on the
nginx output filter facility. Just be careful about data chunk
boundary. The body filter may be called several times for a single
(relatively large) response body given its streaming or unbuffered
nature.
If you want to trigger this via a special response body, then you can
use header_filter_by_lua* and set a flag in ngx.ctx (which is visiable
across various *_by_lua directives in the same request).
At last but not least, be very careful about securiy. You may open up
a hole to allow executing arbitrary code from remote in your nginx
server. Ensure that your backend server emitting Lua code is
completely trusted.
Regards,
-agentzh