How your module plugs into Nginx

In previous articles I have deliberately omitted almost everything related to the question of linking your module with Nginx. It is important, however, that you know about it.

Let’s take a closer look at the metainformation that your module must contain, so that Nginx can initialise and configure it.

This metainformation is represented by the structure ngx_module_t:

struct ngx_module_s {
    [...]
    ngx_uint_t            version;
    void                 *ctx;
    ngx_command_t        *commands;
    ngx_uint_t            type;
    [...]
    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    [...]
    void                (*exit_process)(ngx_cycle_t *cycle);
    void                (*exit_master)(ngx_cycle_t *cycle);
    [...]
};
typedef struct ngx_module_s      ngx_module_t;

Only relevant fields are listed here. The purpose of the fields of this structure is the following:

  • version — contains the version of Nginx API (currently it is 1);
  • ctx — points to a global context of the module (the actual type of structure this pointer points to depends on the value of type field);
  • commands — points to a vector of descriptors of module commands;
  • type — contains the type of the module: NGX_HTTP_MODULE, NGX_EVENT_MODULE, NGX_MAIL_MODULE and others;
  • init_module — points to a handler, that is called upon initialisation of the module in the main process before entering the event loop;
  • init_process — points to a handler, that is called upon initialisation of the module in a worker process;
  • exit_process — points to a handler, that is called upon termination of a worker process;
  • exit_master — points to a handler, that is called upon termination of the master process.

Example:

#include <ngx_config.h>
#include <ngx_core.h>
ngx_module_t  ngx_http_some_module = {
    NGX_MODULE_V1,
    &ngx_http_some_module_ctx,             /* module context */
    ngx_http_some_commands,                /* module directives */
    NGX_HTTP_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};

Note: The instance of ngx_module_t must be declared with extern qualifier. Since all declarations have an extern qualifier by default, it is omitted in our example.

The ./configure script builds a list of pointers to the ngx_module_t structure of all modules available to Nginx. This list is stored in the global vector ngx_modules. Upon start up Nginx configures all the modules in this list with the type NGX_CORE_MODULE. There are a few standard modules with this type. For simplicity, let’s call them core modules. The HTTP module has a configuration directive http in its list of commands. The handler of this directive does the job of configuring and initialising modules with the type NGX_HTTP_MODULE. The mail module has a configuration directive mail in it’s list of commands and it does the same with modules with type NGX_MAIL_MODULE.

So, from a core module point of view, Nginx is nothing more than a configurable event loop. A core module must implement everything that it needs atop of that. So do the http and mail modules.

When you configure Nginx and add some path to the source code of your module with -add-module directive, the configuration script looks for a file named config in that directory and evaluates shell expressions that are specified there. The goal of this file is to set up variables that control the Nginx building process. Here is a list of the most important variables:

Variable name
Purpose
ngx_addon_name The name of the current Nginx addon
NGX_ADDON_SRCS A list of all source files of all addons, that are to be compiled
NGX_ADDON_DEPS A list of all dependent files of all addons (usually header files)
HTTP_MODULES A list of all HTTP modules
HTTP_AUX_FILTER_MODULES A list of all auxiliary  filters
USE_MD5 Specifies whether MD5 support should be enabled (YES/NO)
USE_SHA1 Specifies whether SHA-1 support should be enabled (YES/NO)
USE_ZLIB Specifies whether zlib library support should be enabled (YES/NO)

If you want to refer to a directory that contains files of your module, you can use a variable ngx_addon_dir. Lets look at the example of config file:

ngx_addon_name=ngx_http_sample_module
HTTP_MODULES="$HTTP_MODULES ngx_http_sample_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_sample_module.c"

This configuration file defines a module named ngx_http_sample_module. It extends the list of HTTP modules and the list of addon source files.

Suppose the source files of your module are located in the directory /home/valery/work/nginx-sample-module. In order to plug your module into Nginx you need to configure it in the following way:

path/to/nginx/sources$ ./configure --add-module=/home/valery/work/nginx-sample-module

At this stage the configuration script ./configure will evaluate config file from your module and add all necessary information for building your module to the Makefile. After ./configure has finished, run:

path/to/nginx/sources$ make
path/to/nginx/sources$ make install

This will compile and install a binary of Nginx with your module compiled in. With this binary you can use directives of your module in the configuration file.

As you can see, the amount of information required to link your module with Nginx is minimal. In the next articles, you will see how an HTTP module plugs into Nginx and how to create a core module.

This entry was posted in nginx. Bookmark the permalink.

Comments are closed.