Ngx_http_get_module_loc_conf not returning the right configuration (long)?

Hi,

While debugging my upload progress hack module, I’m stumbling accross
the issue that:
lzcf = ngx_http_get_module_loc_conf(r,
ngx_http_uploadprogress_module);
called in an NGX_HTTP_POST_READ_PHASE handler doesn’t return the right
“location configuration” (or at least not the one I’d like).
In fact most of the module initialisation is based on the limit_zone
module code, because I needed a shared rbtree.
The ngx_http_get_module_loc_conf returns a configuration for which the
pointer to the shm_zone is null.

Here are a few code extract:
static ngx_command_t ngx_http_uploadprogress_commands[] = {

{ ngx_string(“upload_progress”),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,
ngx_http_upload_progress,
0,
0,
NULL },

{ ngx_string(“track_uploads”),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_track_uploads,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },

{ ngx_string(“report_uploads”),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_report_uploads,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
ngx_null_command
};

static ngx_http_module_t ngx_http_uploadprogress_module_ctx = {
NULL, /* preconfiguration /
ngx_http_uploadprogress_init, /
postconfiguration /
NULL, /
create main configuration /
NULL, /
init main configuration /
NULL, /
create server configuration /
NULL, /
merge server configuration /
ngx_http_uploadprogress_create_loc_conf, /
create location
configuration /
ngx_http_uploadprogress_merge_loc_conf /
merge location
configuration */
};

static ngx_int_t
ngx_http_uploadprogress_handler(ngx_http_request_t *r)
{

lzcf = ngx_http_get_module_loc_conf(r,
ngx_http_uploadprogress_module);

if (lzcf->shm_zone == NULL) {
/* HERE is the problem → shm_zone is always NULL */
return NGX_DECLINED;
}

}

static ngx_int_t
ngx_http_uploadprogress_init(ngx_conf_t cf)
{

/
setup a NGX_HTTP_POST_READ_PHASE handler */
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

h = 

ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}

*h = ngx_http_uploadprogress_handler;


}

static void *
ngx_http_uploadprogress_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_uploadprogress_conf_t *conf;

conf = ngx_pcalloc(cf->pool, 

sizeof(ngx_http_uploadprogress_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
return conf;
}

static char *
ngx_http_uploadprogress_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child)
{
ngx_http_uploadprogress_conf_t *prev = parent;
ngx_http_uploadprogress_conf_t *conf = child;

/* inherit zone declared in parent block */
if (conf->shm_zone == NULL) {
*conf = *prev;
}

return NGX_CONF_OK;
}

static char *
ngx_http_upload_progress(ngx_conf_t *cf, ngx_command_t *cmd, void conf)
{

/
creation of the shm_zone */
shm_zone = ngx_shared_memory_add(cf, &value[1], n,
&ngx_http_uploadprogress_module);

}

static char *
ngx_http_track_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_uploadprogress_conf_t *lzcf = conf;

lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0,

&ngx_http_uploadprogress_module);

}

static char *
ngx_http_report_uploads(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_uploadprogress_conf_t *lzcf = conf;

lzcf->shm_zone = ngx_shared_memory_add(cf, &value[1], 0,

&ngx_http_uploadprogress_module);

}

In both ngx_http_report_uploads, ngx_http_track_uploads, the shm_zone is
properly defined (and matches the one really created in
ngx_http_upload_progress).

The configuration file looks like:


http {

upload_progress proxied 1m;

server {
listen 80;
server_name localhost;

location / {
proxy_pass http://127.0.0.1:8080;
track_uploads proxied;
}

location /progress {
report_uploads proxied;
}
}
}

When debugging a request that ends up in the
ngx_http_uploadprogress_handler post read phase handler, I see several
(more than two) location conf merger appearing, and I have exactly two
childs with a defined shm_zone. The merge operation seems OK to me, not
overwriting child configuration.

Any idea what could be wrong ?
Could it be because of the proxy_pass before my own configuration
directive?

Ah, and also I couldn’t get any ngx_log_debugX(NGX_LOG_DEBUG_HTTP…) to
actually print log in the several configuration handlers, is that
normal?

Thanks,

On Mon, Oct 01, 2007 at 09:43:02AM +0200, Brice F. wrote:

While debugging my upload progress hack module, I’m stumbling accross
the issue that:
lzcf = ngx_http_get_module_loc_conf(r,
ngx_http_uploadprogress_module);
called in an NGX_HTTP_POST_READ_PHASE handler doesn’t return the right
“location configuration” (or at least not the one I’d like).

When nginx runs in NGX_HTTP_POST_READ_PHASE, it has server level
configuration.
Then NGX_HTTP_SERVER_REWRITE_PHASE goes, and some location configuration
is
found after NGX_HTTP_FIND_CONFIG_PHASE.

So NGX_HTTP_POST_READ_PHASE is not right place to this.

In fact most of the module initialisation is based on the limit_zone
module code, because I needed a shared rbtree.
The ngx_http_get_module_loc_conf returns a configuration for which the
pointer to the shm_zone is null.

shm_zone should be non-NULL even on this stage because it is inherited
from http.

{ ngx_string(“track_uploads”),
0,
NULL, /* merge server configuration /
if (lzcf->shm_zone == NULL) {
/
setup a NGX_HTTP_POST_READ_PHASE handler */

}
*conf = *prev;
shm_zone = ngx_shared_memory_add(cf, &value[1], n,


track_uploads proxied;
(more than two) location conf merger appearing, and I have exactly two
childs with a defined shm_zone. The merge operation seems OK to me, not
overwriting child configuration.

Any idea what could be wrong ?
Could it be because of the proxy_pass before my own configuration
directive?

Ah, and also I couldn’t get any ngx_log_debugX(NGX_LOG_DEBUG_HTTP…) to
actually print log in the several configuration handlers, is that
normal?

Yes. Enable

#if 0
log->log_level = NGX_LOG_DEBUG_ALL;
#endif

in src/core/ngx_cycle.c