Installing handlers in NGX_HTTP_LOG_PHASE

Maxim Dounin mdounin at mdounin.ru
Wed Dec 23 13:07:56 MSK 2009


Hello!

On Wed, Dec 23, 2009 at 10:48:06AM +0100, Srebrenko Šehić wrote:

> Hi list,
> 
> I'm looking into expanding nginx' Perl hooks to support installing
> handlers for all NGX_HTTP phases. Ultimate goal is to have nginx' Perl
> hooks do all those fancy things Apache's mod_perl can. Like rewriting
> URI, filtering/changing proxied response bodies, etc. As starters, I
> want to implement a handler which will run some Perl code in
> NGX_HTTP_LOG_PHASE. I do, however, have some questions that I hope
> someone can shed some light onto:
> 
> If I register a postconfiguration hook, I'm able to install a handler
> at LOG_PHASE phase:
> 
> static ngx_http_module_t  ngx_http_perl_module_ctx = {
>     ....
>     ngx_http_perl_log_init,                /* postconfiguration */
>     ....
> };
> 
> static ngx_int_t
> ngx_http_perl_log_init(ngx_conf_t *cf)
> {
>     ngx_http_handler_pt        *h;
>     ngx_http_core_main_conf_t  *cmcf;
> 
>     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
> 
>     h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
>     if (h == NULL) {
>         return NGX_ERROR;
>     }
> 
>     *h = ngx_http_perl_log_handler;
> 
>     return NGX_OK;
> }
> 
> Above works just fine.
> 
> However, what I want to achieve is to install the handler
> conditionally. So when you in your nginx.conf say:
> 
> location /
>     perl_log_handler MyModule::log_handler
> 
> I tried the following approach and failed:
> 
> static ngx_command_t  ngx_http_perl_commands[] = {
>     ....
>     { ngx_string("perl_log_handler"),
>       NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
>       ngx_http_perl_handler_init,
>       NGX_HTTP_LOC_CONF_OFFSET,
>       0,
>       NULL },
>     ....
> };
> 
> static char *
> ngx_http_perl_handler_init(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
> {
>     ngx_http_handler_pt        *h;
>     ngx_http_core_main_conf_t  *cmcf;
> 
>     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
> 
>     h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
>     if (h == NULL) {
>         return NGX_CONF_ERROR;
>     }
> 
>     *h = ngx_http_perl_log_handler;
> 
>     return NGX_CONF_OK;
> }
> 
> nginx dies with SIGSEGV upon startup.

This is somewhat expected as phases array are initialized after 
reading configuration (see ngx_http.c for details).  The only 
alternative is SIGBUS, not sure it's better.  :)

> What is the correct approach to conditionally install a handler?

In postconfiguration handler.  Nothing stops you from doing it 
conditionally.

Maxim Dounin



More information about the nginx-devel mailing list