Hello!
On Wed, Oct 16, 2013 at 11:34 PM, Yichun Zhang (agentzh) wrote:
>
> You don't have to do the initialization in the access phase. You're
> just holding the related resources (mostly memory) for longer time
> than needed.
>
> You can initialize in header_filter_by_lua, and only when the backend
> (Apache in your case) returns the "Content-Encoding: gzip" response
> header.
>
Just for the reference, the following self-contained example for doing
gzip inflate with lua-zlib in body_filter_by_lua has been tested on my
side:
lua_package_cpath "/path/to/lua-zlib/?.so;;";
gzip on;
gzip_min_length 1;
server {
listen 8080;
location = /t {
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:$server_port/apache;
header_filter_by_lua '
if ngx.header.content_encoding == "gzip" then
local zlib = require "zlib"
ngx.ctx.inflate = zlib.inflate()
ngx.header.content_length = nil
ngx.header.content_encoding = nil
end
';
body_filter_by_lua '
local inflate = ngx.ctx.inflate
if not inflate then
return
end
local s = ngx.arg[1]
if s ~= "" then
local inflated, eof = inflate(s)
print("inflated: [", inflated, "]") -- for debugging
if inflated ~= "" then
inflated = string.gsub(inflated, "\\n", "")
local new = "{" .. string.upper(inflated)
.. "}\\n"
ngx.arg[1] = new
else
ngx.arg[1] = nil
end
end
';
}
# for mocking the apache backend
location = /apache {
default_type text/html;
content_by_lua '
for i = 1, 10 do
ngx.say(i .. "hello world" .. i)
ngx.flush()
ngx.sleep(0.2)
end
';
}
} # server
Here we use ngx_lua to mock the Apache backend service, /apache, in
the same Nginx server instance. The main entry point is /t, where it
uses proxy_pass to talk to /apache over HTTP 1.1 and do the gzip
decompression and data modification in place in body_filter_by_lua.
Here we use nginx's standard ngx_gzip module to do the gzip
(re)compression for us right after every time body_filter_by_lua is
run.
Here is the test result using curl:
$ curl -i --compressed localhost:8080/t
HTTP/1.1 200 OK
Server: nginx/1.4.2
Date: Thu, 17 Oct 2013 22:46:03 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Content-Encoding: gzip
{1HELLO WORLD1}
{2HELLO WORLD2}
{3HELLO WORLD3}
{4HELLO WORLD4}
{5HELLO WORLD5}
{6HELLO WORLD6}
{7HELLO WORLD7}
{8HELLO WORLD8}
{9HELLO WORLD9}
{10HELLO WORLD10}
Note the "Content-Encoding: gzip" response header, which indicates
that the final response is indeed gzip compressed.
And then, we can check nginx's error.log file for the debugging logs
genereated by the print() function in our body_filter_by_lua (the
output is edited a bit to save some space here):
$ grep inflated logs/error.log
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [1hello world1
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [2hello world2
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [3hello world3
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [4hello world4
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [5hello world5
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [6hello world6
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [7hello world7
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [8hello world8
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [9hello world9
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10:
inflated: [10hello world10
[notice] 11550#0: *4 [lua] [string "body_filter_by_lua"]:10: inflated: []
Please note how the response body data from /apache is inflated by our
body_filter_by_lua chunk by chunk.
Best regards,
-agentzh