openresty / lua-nginx-module

Embed the Power of Lua into NGINX HTTP servers
https://openresty.org/
11.24k stars 2.02k forks source link

stange behaviour when using `body_filter_by_lua_file` together with `content_by_lua_block` #1826

Open suikabreaker opened 3 years ago

suikabreaker commented 3 years ago
access_by_lua_block {
    if ngx.var.test then -- for reproducing the behaviour
        ngx.exit(ngx.HTTP_FORBIDDEN)
    end
}
content_by_lua_file './echo.lua';
body_filter_by_lua_block{
    ngx.arg[1] = string.upper(ngx.arg[1])
}
-- ./echo.lua which content is not really matter
for k, v in pairs((ngx.req.get_headers())) do
  ngx.say("<p>",k, ":", v,"</p>");
end

It's works fine as long as no "test" parameter is sent. And after that, it's OK to keep responsing with capitallized 403 page to "test" request. But it fails to response to normal requsest, with logs saying:

failed to run body_filter_by_lua*: ./echo.lua:1: API disabled in the context of body_filter_by_lua*

As the msg suggests, I believe that body_filter_by_lua* is not supposed to use together with content_by_lua*, but it didn't shows up until first forbidden request.

envrioment:

windows 10 nginx version: openresty/1.17.8.2 built by gcc 7.3.0 (Rev1, Built by MSYS2 project) built with OpenSSL 1.1.1g 21 Apr 2020 TLS SNI support enabled configure arguments: --prefix=. --with-cc-opt='-O2 -DFD_SETSIZE=1024' --add-module=../ngx_devel_kit-0.3.1 --add-module=../echo-nginx-module-0.62 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.32 --add-module=../ngx_lua-0.10.17 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../ngx_stream_lua-0.0.8 --with-cc=gcc --with-ipv6 --sbin-path=nginx.exe --with-pcre-jit --with-ipv6 --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_auth_request_module --with-http_secure_link_module --with-http_random_index_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-select_module --with-pcre=/home/agentzh/work/openresty-1.17.8.2/objs/lib/pcre-8.44 --with-zlib=/home/agentzh/work/openresty-1.17.8.2/objs/lib/zlib-1.2.11 --with-openssl=/home/agentzh/work/openresty-1.17.8.2/objs/lib/openssl-1.1.1g --with-openssl-opt=-g --with-pcre-opt=-g --with-zlib-opt=-g --with-stream --with-stream_ssl_preread_module --with-http_ssl_module

spacewander commented 3 years ago

Can't reproduce in my side.

Got:

 ¥ curl 127.0.0.1:28000/x -i
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Mon, 09 Nov 2020 10:14:52 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>

with

worker_processes 1;
daemon off;
error_log stderr error;
events {
    worker_connections 65535;
}
http {
    server {
        listen 28000 reuseport;

        location / {
            access_by_lua_block {
                    if ngx.var.test then -- for reproducing the behaviour
                                ngx.exit(ngx.HTTP_FORBIDDEN)
                                        end
            }
            content_by_lua_file './echo.lua';
            body_filter_by_lua_block{
                    ngx.arg[1] = string.upper(ngx.arg[1])
            }
        }
    }
}
suikabreaker commented 3 years ago

Can't reproduce in my side.

Got:

 ¥ curl 127.0.0.1:28000/x -i
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Mon, 09 Nov 2020 10:14:52 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>

with

worker_processes 1;
daemon off;
error_log stderr error;
events {
    worker_connections 65535;
}
http {
    server {
        listen 28000 reuseport;

        location / {
            access_by_lua_block {
                    if ngx.var.test then -- for reproducing the behaviour
                                ngx.exit(ngx.HTTP_FORBIDDEN)
                                        end
            }
            content_by_lua_file './echo.lua';
            body_filter_by_lua_block{
                    ngx.arg[1] = string.upper(ngx.arg[1])
            }
        }
    }
}

try to curl 127.0.0.1:28000/?test=test and then 127.0.0.1:28000

spacewander commented 3 years ago
¥ curl '127.0.0.1:28000/?test=test'
<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>
 ¥ curl '127.0.0.1:28000' -i
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Tue, 10 Nov 2020 02:54:20 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>
suikabreaker commented 3 years ago
¥ curl '127.0.0.1:28000/?test=test'
<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>
 ¥ curl '127.0.0.1:28000' -i
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Tue, 10 Nov 2020 02:54:20 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>

my fault. change condition to if ngx.req.get_uri_args().test then and it should reproduce

spacewander commented 3 years ago
¥ curl '127.0.0.1:28000/?test=test'
<HTML>
<HEAD><TITLE>403 FORBIDDEN</TITLE></HEAD>
<BODY>
<CENTER><H1>403 FORBIDDEN</H1></CENTER>
<HR><CENTER>OPENRESTY/1.17.8.2</CENTER>
</BODY>
</HTML>
 ¥ curl '127.0.0.1:28000' -i
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Tue, 10 Nov 2020 03:22:45 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>
suikabreaker commented 3 years ago
¥ curl '127.0.0.1:28000/?test=test'
<HTML>
<HEAD><TITLE>403 FORBIDDEN</TITLE></HEAD>
<BODY>
<CENTER><H1>403 FORBIDDEN</H1></CENTER>
<HR><CENTER>OPENRESTY/1.17.8.2</CENTER>
</BODY>
</HTML>
 ¥ curl '127.0.0.1:28000' -i
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Tue, 10 Nov 2020 03:22:45 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

<P>HOST:127.0.0.1:28000</P>
<P>ACCEPT:*/*</P>
<P>USER-AGENT:CURL/7.68.0</P>

I figured out that this is needed to reproduce the hehaviour:

lua_code_cache off;
suikabreaker commented 3 years ago

and this is the full content of echo.lua:

ngx.say("<html><head></head><body>");   

local args = ngx.req.get_post_args();
ngx.say("<h2>basic</h2>");
ngx.say("<p>method: ", ngx.req.get_method(),"</p>");
ngx.say("<p>url: ", ngx.var.request_uri,"</p>");
ngx.say("<p>version : ", ngx.req.http_version(),"</p>");
ngx.say("<h2>args","</h2>");
ngx.say("<h3>get","</h3>");
local args, err = ngx.req.get_uri_args()
if not err then 
for key, val in pairs(args) do
    if type(val) == "table" then
        ngx.say("<p>",key, ": { ",table.concat(val, ", "), "}","</p>")
    else
        ngx.say("<p>",key, ": { ",val, "}","</p>")
    end
end
end
ngx.say("<h3>post</h3>");
args, err = ngx.req.get_post_args()
if not err then 
for key, val in pairs(args) do
    if type(val) == "table" then
        ngx.say("<p>",key, ": { ",table.concat(val, ", "), " }","</p>")
    else
        ngx.say("<p>",key, ": { ", val, " }","</p>")
    end
end
end
ngx.say("<h2>parsed_header</h2>");
for k, v in pairs((ngx.req.get_headers())) do
  ngx.say("<p>",k, ":", v,"</p>");
end

ngx.say("<h2>","headers","</h2>");
ngx.say("<textarea>",ngx.req.raw_header(),"</textarea>")
ngx.say("<h2>","body","</h2>");
local body = ngx.req.get_body_data() or ""
ngx.say("<textarea>",body,"</textarea>");

ngx.say("</body></html>");

plus we need lua_need_request_body on; for post_args.