Open-Source Wikis

/

nginx

/

Primitives

/

Module (`ngx_module_t`)

nginx/nginx

Module (ngx_module_t)

Active contributors: Sergey Kandaurov, Maxim Dounin

What it is

A module is the unit of feature in nginx. Every directive, every protocol handler, every variable, every load balancer, every filter is registered through an ngx_module_t. The static array ngx_modules[] (generated at build time by auto/modules into objs/ngx_modules.c) is the source of truth for what features the binary has. Dynamic modules use the same struct but ship as .so files.

Definition

src/core/ngx_module.h:

struct ngx_module_s {
    ngx_uint_t            ctx_index;        /* index within its type */
    ngx_uint_t            index;            /* index across all modules */

    char                 *name;             /* set by NGX_MODULE_V1 / dynamic */

    ngx_uint_t            spare0;
    ngx_uint_t            spare1;

    ngx_uint_t            version;          /* nginx_version */
    const char           *signature;        /* compile-time feature mask */

    void                 *ctx;              /* type-specific hook table */
    ngx_command_t        *commands;         /* directives this module owns */
    ngx_uint_t            type;             /* NGX_*_MODULE constant */

    /* lifecycle hooks */
    ngx_int_t           (*init_master)(ngx_log_t *log);
    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
    void                (*exit_thread)(ngx_cycle_t *cycle);
    void                (*exit_process)(ngx_cycle_t *cycle);
    void                (*exit_master)(ngx_cycle_t *cycle);

    /* padding for ABI evolution */
    uintptr_t             spare_hook0;
    /* ... 7 more spare hooks ... */
};

The NGX_MODULE_V1 macro initializes the version + signature + index fields; NGX_MODULE_V1_PADDING zeroes the spare hooks. Together they keep the struct layout stable across nginx versions so dynamic modules built against one version can load into another (within the bounds of the signature compatibility check).

Module types

type is one of:

Constant Hex "Friendly name" Hook table type
NGX_CORE_MODULE 0x434F5245 "CORE" ngx_core_module_t
NGX_EVENT_MODULE 0x544E5645 "EVNT" ngx_event_module_t
NGX_HTTP_MODULE 0x50545448 "HTTP" ngx_http_module_t
NGX_MAIL_MODULE 0x4C49414D "MAIL" ngx_mail_module_t
NGX_STREAM_MODULE 0x4d525453 "STRM" ngx_stream_module_t
NGX_CONF_MODULE 0x464E4F43 "CONF" (the include directive)

The 4-character ASCII tags are the integer values (read backwards on x86). They're a sanity check at module load time.

Hook tables

The ctx pointer points to a type-specific struct that adds module-type-specific hooks beyond the lifecycle ones in ngx_module_t. For HTTP:

typedef struct {
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);    /* register variables */
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);   /* attach phase handlers */

    void       *(*create_main_conf)(ngx_conf_t *cf);
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);

    void       *(*create_srv_conf)(ngx_conf_t *cf);
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);

    void       *(*create_loc_conf)(ngx_conf_t *cf);
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);
} ngx_http_module_t;

Hooks fire in this order:

  1. preconfiguration — before parsing. Modules register variables here.
  2. Parsing — directives from commands[] fire in order they appear in nginx.conf. create_*_conf allocates, the directive's setter fills.
  3. init_main_conf / merge_*_conf — after parsing. Fill in defaults, merge from outer scope.
  4. postconfiguration — attach phase handlers, capture filter chain pointers.

Setting the right hook for a feature is the central question when writing a module.

Lifecycle hooks

Beyond the type-specific hooks, every module has the lifecycle ones in ngx_module_t:

Hook Fires
init_master Once in the master before the first cycle. Almost always NULL.
init_module After ngx_init_cycle builds a new cycle (startup + every reload)
init_process After fork(), in each worker. Open per-worker resources.
init_thread (Reserved; not currently used.)
exit_thread (Reserved.)
exit_process Worker is exiting. Close per-worker resources.
exit_master Master is exiting. Almost always NULL.

Modules typically use init_module to set up shared zones and init_process to open per-worker fds.

commands[]

The directive table. ngx_command_t:

struct ngx_command_s {
    ngx_str_t             name;       /* directive name */
    ngx_uint_t            type;       /* context + arity flags */
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;       /* which conf to write into */
    ngx_uint_t            offset;     /* offset within that conf */
    void                 *post;       /* extra arg for the setter */
};

commands[] is terminated by ngx_null_command. See systems/configuration for the list of context flags, common setters, and how the parser dispatches directives.

A minimal HTTP module

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

typedef struct {
    ngx_flag_t  enable;
} ngx_http_my_loc_conf_t;

static ngx_int_t ngx_http_my_handler(ngx_http_request_t *r);
static char *ngx_http_my_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static void *ngx_http_my_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_my_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);

static ngx_command_t  ngx_http_my_commands[] = {
    { ngx_string("my_directive"),
      NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_my_loc_conf_t, enable),
      NULL },
    ngx_null_command
};

static ngx_http_module_t  ngx_http_my_module_ctx = {
    NULL,                                /* preconfiguration  */
    ngx_http_my_init,                    /* postconfiguration */
    NULL,                                /* create main conf  */
    NULL,                                /* init main conf    */
    NULL,                                /* create srv conf   */
    NULL,                                /* merge  srv conf   */
    ngx_http_my_create_loc_conf,         /* create loc conf   */
    ngx_http_my_merge_loc_conf,          /* merge  loc conf   */
};

ngx_module_t  ngx_http_my_module = {
    NGX_MODULE_V1,
    &ngx_http_my_module_ctx,             /* module context */
    ngx_http_my_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
};

static ngx_int_t
ngx_http_my_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_ACCESS_PHASE].handlers);
    if (h == NULL) return NGX_ERROR;
    *h = ngx_http_my_handler;
    return NGX_OK;
}

Build via --add-module=/path/to/dir (static) or --add-dynamic-module=... (loadable .so).

Module signature

NGX_MODULE_SIGNATURE is a compile-time string of 0/1 bits encoding which NGX_HAVE_* features the module was built against. At module-load time, the host nginx checks the signature matches; if not, load_module refuses. This is what prevents loading a module built against --with-debug into a non-debug nginx, or vice versa.

The signature is generated from NGX_MODULE_SIGNATURE_0 through NGX_MODULE_SIGNATURE_34 (see src/core/ngx_module.h).

ngx_modules[] and ngx_module_names[]

Both are auto-generated by auto/modules and live in objs/ngx_modules.c:

ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    /* ... etc ... */
    NULL
};

char *ngx_module_names[] = {
    "ngx_core_module",
    "ngx_errlog_module",
    /* ... */
    NULL
};

The order matters: init_module, init_process, and especially filter-chain registration all depend on it. auto/modules uses an explicit ORDER list to keep things consistent across builds.

Cross-references

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Module (`ngx_module_t`) – nginx wiki | Factory