Terminate request from access_by_lua

838 views
Skip to first unread message

an...@khalikov.ru

unread,
Nov 11, 2014, 1:47:42 AM11/11/14
to openre...@googlegroups.com
Hi there

I am a bit confused about difference between what official documentation says and how lua module really behaves. It is written in access_by_lua docs that:

To terminate the current request from within a access_by_lua handler, calling ngx.exit with status >= 200 (ngx.HTTP_OK) and status < 300 (ngx.HTTP_SPECIAL_RESPONSE) for successful quits and ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) (or its friends) for failures.

I tried 2 ways to accomplish this:

return ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)

and

ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
return ngx.exit(ngx.HTTP_OK)

in my access_by_lua_file part. But every request still goes through header_filter_by_lua_file, even those who meant to be terminated at access phase. Same problem for ngx.HTTP_FORBIDDEN status.

Is it a bug or just my misunderstanding of request flow?

What I would want to do is to write a counter code that would collect response codes from upstream apache, but if request is cancelled at access phase, my counter should not be affected by these requests. Counter lives in ngx.shared and gets flushed every few minutes. If the current behavior is ok and header_filter handler is meant to be called on every request no matter of what happened at access phase, then the only way to accomplish my task I can think of is to decrease counter at access phase if I want to terminate request, then my header_filter would increase it back to zero for cancelled requests. Any other ideas may be?

Thanks in advance!

Yichun Zhang (agentzh)

unread,
Nov 11, 2014, 3:25:22 PM11/11/14
to openresty-en
Hello!

On Mon, Nov 10, 2014 at 10:47 PM, <an...@khalikov.ru> wrote:
> To terminate the current request from within a access_by_lua handler,
> calling ngx.exit with status >= 200 (ngx.HTTP_OK) and status < 300
> (ngx.HTTP_SPECIAL_RESPONSE) for successful quits and
> ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) (or its friends) for failures.
>

The "terminate" word here means terminating the nginx request
processing phases, that is, it will not proceed to the later phases
like the "content" phase.

> I tried 2 ways to accomplish this:
> return ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)
> and
> ngx.status = ngx.HTTP_SERVICE_UNAVAILABLE
> return ngx.exit(ngx.HTTP_OK)
> in my access_by_lua_file part. But every request still goes through
> header_filter_by_lua_file, even those who meant to be terminated at access
> phase. Same problem for ngx.HTTP_FORBIDDEN status.
>

You're "terminating" the current request by returning an HTTP error
code which will trigger sending out a corresponding special error
page. This response will surely trigger nginx header filters and body
filters to run. This is very natural.

If you want to terminate the current request hard by aborting the
downstream connection without sending anything back, then you should
use ngx.exit(444) here instead.

> Is it a bug or just my misunderstanding of request flow?
>

See above.

> What I would want to do is to write a counter code that would collect
> response codes from upstream apache, but if request is cancelled at access
> phase, my counter should not be affected by these requests.

Well, the simplest way is to set custom flags in ngx.ctx [1], check
the flags in your log_by_lua, and insert data to shared dict based on
the flags conditionally.

Regards,
-agentzh

[1] https://github.com/openresty/lua-nginx-module#ngxctx

an...@khalikov.ru

unread,
Nov 12, 2014, 12:54:32 AM11/12/14
to openre...@googlegroups.com
> [1] https://github.com/openresty/lua-nginx-module#ngxctx 

I've completely missed this part. Thank you! This is exactly what I needed :)
Reply all
Reply to author
Forward
0 new messages