Enough distraction (the web is good at that). I started to focus on the development of my HttpRRDModule. So, here what I went through trying to get the bare bone infrastructure of the module:
- Get the nginx headers in the C file (copy/paste from any module, they are all the same).
- Create the
config
file. It's the file used by nginx to integrate your module into its build system. Pretty much all exemples are the same. Take Evan Miller's one. - Build the thing (
configure --add-module ...; make
). Now, we have a big nothing that compiles. It's a good start. ;) - Code the request handler. You know, the thing taking a
ngx_http_request_t
as argument and returning angx_int_t
. You code something close to the empty function and you try to compile it. And that's where troubles start... It does not compile any more. The reason is fairly simple: nginx compiler settings are strict enough to fail the compilation in case of unused functions. I cannot say I'm complaining about this, I love using the compiler as much as possible to detect problems. But, this is honestly the first time I run into a project which default settings are to fail on unused functions. - So, I went ahead and added all the magic mantras that register the handler with nginx. Declaring the
ngx_http_module_t
, thengx_command_t
and attaching my function as handler with something like:clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
It's pretty much the example you find everywhere.
clcf->handler = ngx_http_rrd_handler;
And at this point I look at the thing and am thinking "I'm creating a directive for nothing". Let's say I don't even want a directive, I just want to register my module and have it handle all requests. Yes, it's extreme as in real life I would probably limit my module to a location. But it's a good exercise. So, instead of having my code that registers the handler invoked as the processor of a directive, I make it called as the postconfiguration method of my module (see appropriate field in
ngx_http_module_t
structure). And...nothing works. At this point, I start wondering very seriously how this works. So, I start checking: my registration is called. It's just that nginx never gives my module a chance to handle the request. That's when I started adding breakpoints and watched the thing run in details.Where you have to start looking is the
ngx_http_core_content_phase
function (ngx_http_core_module.c
) there is a test to see if the request has a content_handler: if (r->content_handler)
and in my case (handler attached from the postconfiguration) this is NULL. So, nginx runs all the other modules (including the index, auto-index and static built-in modules) and finally declares '404 - NOT FOUND'. All I have to find is "who is setting this r->content_handler
. Of course, it's one of the previous phases. It's actually the "find config" phase. To be more specific look at functions ngx_http_core_find_config_phase
and ngx_http_update_location_config
. As I keep debugging, I notice that the handler is not retrieved from the location configuration of the http_core_module. And that's where the trick is: in the postconfiguration method, I can call ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module)
but it pretty much returns crap. Or at least what it returns is not tied to a location. Therefore, I was registering my handler in a location that does not exist.That's long enough for today. I'll tell you the rest of this story in my next post with the two ways you can register your module: as a HTTP handler or as content phase handler.
No comments:
Post a Comment