quick start on writing a module?

Maxim Dounin mdounin at mdounin.ru
Wed Jun 16 14:35:01 MSD 2010


Hello!

On Wed, Jun 16, 2010 at 02:29:43AM -0700, Mark Harrison wrote:

> I'd like to convert an apache module I've written to work
> under nginx.  Can somebody loan me a clue for getting started?

It's probably good idea to start from here:

http://nginx.org/en/links.html
http://wiki.nginx.org/Nginx3rdPartyModules
http://wiki.nginx.org/NginxResources#Developer_resources

Note well: in most cases it's good idea to rewrite module from 
scratch instead of trying to adopt something written for Apache.

> Background
> ----------
> 
> The logic is pretty simple:
> 
>   1.  based on the input URI, determine what file will be
>       sent.  this will possibly involved a (cached) db lookup.
> 
>   2a. set these headers:
> 
>         Content-disposition:
>         ETag:
>         X-mod_asset-version: (my custom header)
> 
>   2b. set mime type.
> 
>   3.  allow nginx to send the bytes of the file.  Hopefully
>       it will handle these headers:
> 
>         Last-Modified:
>         Content-Length:
>         Accept-Ranges:
>         Content-Range:
>         Content-Length:

Problematic part is "db lookup".  In nginx you have to do it in 
non-blocking way, and this isn't something readily available in 
database client libraries.  You may want to deligate this part to 
some backend or already available modules like ngx_postgres 
(http://wiki.nginx.org/Nginx3rdPartyModules#Postgres_Module).

> Questions
> ---------
> 
> For 2b, this is the proper way?
> 
>     r->headers_out.content_type.len = sizeof("image/gif") - 1;
>     r->headers_out.content_type.data = (u_char *) "image/gif";

No.

For 0.7.* use:

    r->headers_out.content_type_len = sizeof("image/gif") - 1;
    r->headers_out.content_type.len = sizeof("image/gif") - 1;
    r->headers_out.content_type.data = (u_char *) "image/gif";

For 0.8.37+ use ngx_str_set() macro to set string, i.e.

    r->headers_out.content_type_len = sizeof("image/gif") - 1;
    ngx_str_set(&r->headers_out.content_type, "image/gif");

>     Is there a special way to malloc the .data so that it
>     will be freed automatically when the request is complete?

In the above case you don't need to allocate anything as it uses 
constants strings.  For dynamic allocations use 
ngx_pool_alloc(r->pool).

> For 3, should I be using X-Accel-Redirect?
> 
>     add_header("X-Accel-Redirect: /protected/iso.img");
> 
> If so, then I can simply set my headers and pass along to the next
> phase?

No.  X-Accel-Redirect is special header understood by upstream 
module (proxy, fastcgi) in backend responses.  In your own module 
you have to use ngx_http_internal_redirect() function for this.

> Any simple example modules I can use as a starting point?

For simple content generation see ngx_http_empty_gif_module.c, 
ngx_http_static_module.c, ngx_http_flv_module.c.

For simple examples of internal redirect usage see 
ngx_http_index_module.c, ngx_http_random_index_module.c.

Maxim Dounin



More information about the nginx mailing list