Перейти к содержанию

Configuration Directives

This guide explains how to define custom directives in NGINX modules.


Directive Structure

Every directive is defined by ngx_command_t:

struct ngx_command_t {
    ngx_str_t             name;      /* Directive name */
    ngx_uint_t            type;      /* Where valid + argument count */
    char               *(*set)();    /* Handler function */
    ngx_uint_t            conf;      /* Configuration offset */
    ngx_uint_t            offset;    /* Field offset in struct */
    void                 *post;      /* Additional data */
};

Directive Types

Location Flags

Where the directive can appear:

NGX_MAIN_CONF       /* Main context (outside blocks) */
NGX_EVENT_CONF      /* events { } block */
NGX_HTTP_MAIN_CONF  /* http { } block */
NGX_HTTP_SRV_CONF   /* server { } block */
NGX_HTTP_LOC_CONF   /* location { } block */
NGX_HTTP_UPS_CONF   /* upstream { } block */
NGX_HTTP_SIF_CONF   /* server if { } block */
NGX_HTTP_LIF_CONF   /* location if { } block */
NGX_HTTP_LMT_CONF   /* limit_except { } block */

Argument Flags

NGX_CONF_NOARGS     /* No arguments: directive; */
NGX_CONF_TAKE1      /* 1 argument: directive value; */
NGX_CONF_TAKE2      /* 2 arguments: directive val1 val2; */
NGX_CONF_TAKE3      /* 3 arguments */
NGX_CONF_TAKE4      /* 4 arguments */
NGX_CONF_TAKE5      /* 5 arguments */
NGX_CONF_TAKE6      /* 6 arguments */
NGX_CONF_TAKE7      /* 7 arguments */

NGX_CONF_TAKE12     /* 1 or 2 arguments */
NGX_CONF_TAKE13     /* 1 or 3 arguments */
NGX_CONF_TAKE23     /* 2 or 3 arguments */
NGX_CONF_TAKE123    /* 1, 2, or 3 arguments */
NGX_CONF_TAKE1234   /* 1 to 4 arguments */

NGX_CONF_1MORE      /* At least 1 argument */
NGX_CONF_2MORE      /* At least 2 arguments */

NGX_CONF_FLAG       /* on|off flag */
NGX_CONF_BLOCK      /* Block directive { } */
NGX_CONF_ANY        /* Any number of arguments */

Built-in Handlers

NGINX provides handlers for common value types.

Flag (on/off)

typedef struct {
    ngx_flag_t enable;
} ngx_http_mymodule_conf_t;

static ngx_command_t commands[] = {
    {
        ngx_string("mymodule_enable"),
        NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
        ngx_conf_set_flag_slot,
        NGX_HTTP_LOC_CONF_OFFSET,
        offsetof(ngx_http_mymodule_conf_t, enable),
        NULL
    },
    ngx_null_command
};

Usage: mymodule_enable on; or mymodule_enable off;

String

typedef struct {
    ngx_str_t name;
} ngx_http_mymodule_conf_t;

{
    ngx_string("mymodule_name"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
    ngx_conf_set_str_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mymodule_conf_t, name),
    NULL
}

Usage: mymodule_name "my-value";

Number (unsigned)

typedef struct {
    ngx_uint_t count;
} ngx_http_mymodule_conf_t;

{
    ngx_string("mymodule_count"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
    ngx_conf_set_num_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mymodule_conf_t, count),
    NULL
}

Usage: mymodule_count 10;

Size (with k/m suffix)

typedef struct {
    size_t buffer_size;
} ngx_http_mymodule_conf_t;

{
    ngx_string("mymodule_buffer_size"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
    ngx_conf_set_size_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mymodule_conf_t, buffer_size),
    NULL
}

Usage: mymodule_buffer_size 4k; or mymodule_buffer_size 1m;

Time (with s/m/h/d suffix)

typedef struct {
    ngx_msec_t timeout;
} ngx_http_mymodule_conf_t;

{
    ngx_string("mymodule_timeout"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
    ngx_conf_set_msec_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mymodule_conf_t, timeout),
    NULL
}

Usage: mymodule_timeout 30s; or mymodule_timeout 5m;

Enum

typedef struct {
    ngx_uint_t method;
} ngx_http_mymodule_conf_t;

static ngx_conf_enum_t methods[] = {
    { ngx_string("simple"), 0 },
    { ngx_string("advanced"), 1 },
    { ngx_string("expert"), 2 },
    { ngx_null_string, 0 }
};

{
    ngx_string("mymodule_method"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
    ngx_conf_set_enum_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mymodule_conf_t, method),
    &methods
}

Usage: mymodule_method advanced;

Bitmask

#define METHOD_GET     0x0001
#define METHOD_POST    0x0002
#define METHOD_PUT     0x0004
#define METHOD_DELETE  0x0008

typedef struct {
    ngx_uint_t methods;
} ngx_http_mymodule_conf_t;

static ngx_conf_bitmask_t method_masks[] = {
    { ngx_string("GET"), METHOD_GET },
    { ngx_string("POST"), METHOD_POST },
    { ngx_string("PUT"), METHOD_PUT },
    { ngx_string("DELETE"), METHOD_DELETE },
    { ngx_null_string, 0 }
};

{
    ngx_string("mymodule_methods"),
    NGX_HTTP_LOC_CONF | NGX_CONF_1MORE,
    ngx_conf_set_bitmask_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mymodule_conf_t, methods),
    &method_masks
}

Usage: mymodule_methods GET POST PUT;


Custom Handlers

For complex directives, write a custom handler:

Single Argument

static char *
ngx_http_mymodule_set_value(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_mymodule_conf_t *mcf = conf;
    ngx_str_t *value;

    value = cf->args->elts;
    /* value[0] = directive name */
    /* value[1] = first argument */

    if (value[1].len == 0) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "empty value in \"%V\" directive", &value[0]);
        return NGX_CONF_ERROR;
    }

    mcf->my_value = value[1];

    return NGX_CONF_OK;
}

Multiple Arguments

static char *
ngx_http_mymodule_set_pair(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_mymodule_conf_t *mcf = conf;
    ngx_str_t *value;
    ngx_int_t n;

    value = cf->args->elts;
    /* value[0] = directive name */
    /* value[1] = key */
    /* value[2] = val */

    mcf->key = value[1];

    n = ngx_atoi(value[2].data, value[2].len);
    if (n == NGX_ERROR || n < 0) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "invalid number \"%V\"", &value[2]);
        return NGX_CONF_ERROR;
    }

    mcf->val = n;

    return NGX_CONF_OK;
}

{
    ngx_string("mymodule_pair"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2,
    ngx_http_mymodule_set_pair,
    NGX_HTTP_LOC_CONF_OFFSET,
    0,
    NULL
}

Usage: mymodule_pair key 42;

Content Handler Directive

static char *
ngx_http_mymodule_handler_cmd(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_mymodule_handler;

    return NGX_CONF_OK;
}

{
    ngx_string("mymodule"),
    NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
    ngx_http_mymodule_handler_cmd,
    0,
    0,
    NULL
}

Usage:

location /api {
    mymodule;
}


Configuration Contexts

Creating Configuration

static ngx_http_module_t ngx_http_mymodule_module_ctx = {
    NULL,                               /* preconfiguration */
    ngx_http_mymodule_init,             /* postconfiguration */

    ngx_http_mymodule_create_main_conf, /* create main configuration */
    ngx_http_mymodule_init_main_conf,   /* init main configuration */

    ngx_http_mymodule_create_srv_conf,  /* create server configuration */
    ngx_http_mymodule_merge_srv_conf,   /* merge server configuration */

    ngx_http_mymodule_create_loc_conf,  /* create location configuration */
    ngx_http_mymodule_merge_loc_conf    /* merge location configuration */
};

Create Location Config

static void *
ngx_http_mymodule_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_mymodule_conf_t *conf;

    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_mymodule_conf_t));
    if (conf == NULL) {
        return NULL;
    }

    /* Set unset values */
    conf->enable = NGX_CONF_UNSET;
    conf->count = NGX_CONF_UNSET_UINT;
    conf->timeout = NGX_CONF_UNSET_MSEC;
    conf->buffer_size = NGX_CONF_UNSET_SIZE;

    return conf;
}

Merge Configuration

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

    ngx_conf_merge_value(conf->enable, prev->enable, 0);
    ngx_conf_merge_uint_value(conf->count, prev->count, 10);
    ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 30000);
    ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 4096);
    ngx_conf_merge_str_value(conf->name, prev->name, "default");

    /* Validation */
    if (conf->count == 0) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "mymodule_count must be greater than 0");
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}

Accessing Configuration

At Runtime

static ngx_int_t
ngx_http_mymodule_handler(ngx_http_request_t *r)
{
    ngx_http_mymodule_conf_t *conf;

    /* Get location config */
    conf = ngx_http_get_module_loc_conf(r, ngx_http_mymodule_module);

    if (!conf->enable) {
        return NGX_DECLINED;
    }

    /* Use conf->timeout, conf->buffer_size, etc. */
}

During Configuration

static char *
ngx_http_mymodule_directive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;
    ngx_http_mymodule_main_conf_t *mmcf;

    /* Get core location config */
    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

    /* Get our main config */
    mmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_mymodule_module);

    return NGX_CONF_OK;
}

Merge Macros

/* Flag (0 or 1) */
ngx_conf_merge_value(conf->enable, prev->enable, 0);

/* Unsigned int */
ngx_conf_merge_uint_value(conf->count, prev->count, 10);

/* Size */
ngx_conf_merge_size_value(conf->size, prev->size, 4096);

/* Milliseconds */
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000);

/* Seconds */
ngx_conf_merge_sec_value(conf->interval, prev->interval, 60);

/* String */
ngx_conf_merge_str_value(conf->name, prev->name, "default");

/* Pointer */
ngx_conf_merge_ptr_value(conf->handler, prev->handler, NULL);

/* Bitmask */
ngx_conf_merge_bitmask_value(conf->methods, prev->methods,
                             (NGX_CONF_BITMASK_SET | METHOD_GET));

/* Buffer */
ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, 4096);

Complete Example

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

typedef struct {
    ngx_flag_t  enable;
    ngx_str_t   message;
    ngx_uint_t  count;
    ngx_msec_t  timeout;
} ngx_http_example_loc_conf_t;

static void *ngx_http_example_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_example_merge_loc_conf(ngx_conf_t *cf,
    void *parent, void *child);
static char *ngx_http_example(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_example_handler(ngx_http_request_t *r);

static ngx_command_t ngx_http_example_commands[] = {

    { ngx_string("example"),
      NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
      ngx_http_example,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },

    { ngx_string("example_enable"),
      NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_example_loc_conf_t, enable),
      NULL },

    { ngx_string("example_message"),
      NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_example_loc_conf_t, message),
      NULL },

    { ngx_string("example_count"),
      NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
      ngx_conf_set_num_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_example_loc_conf_t, count),
      NULL },

    { ngx_string("example_timeout"),
      NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
      ngx_conf_set_msec_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_example_loc_conf_t, timeout),
      NULL },

    ngx_null_command
};

static ngx_http_module_t ngx_http_example_module_ctx = {
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    ngx_http_example_create_loc_conf,
    ngx_http_example_merge_loc_conf
};

ngx_module_t ngx_http_example_module = {
    NGX_MODULE_V1,
    &ngx_http_example_module_ctx,
    ngx_http_example_commands,
    NGX_HTTP_MODULE,
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    NGX_MODULE_V1_PADDING
};

static void *
ngx_http_example_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_example_loc_conf_t *conf;

    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_example_loc_conf_t));
    if (conf == NULL) {
        return NULL;
    }

    conf->enable = NGX_CONF_UNSET;
    conf->count = NGX_CONF_UNSET_UINT;
    conf->timeout = NGX_CONF_UNSET_MSEC;

    return conf;
}

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

    ngx_conf_merge_value(conf->enable, prev->enable, 1);
    ngx_conf_merge_str_value(conf->message, prev->message, "Hello!");
    ngx_conf_merge_uint_value(conf->count, prev->count, 1);
    ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 30000);

    return NGX_CONF_OK;
}

static char *
ngx_http_example(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_example_handler;

    return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_example_handler(ngx_http_request_t *r)
{
    ngx_http_example_loc_conf_t *conf;

    conf = ngx_http_get_module_loc_conf(r, ngx_http_example_module);

    if (!conf->enable) {
        return NGX_DECLINED;
    }

    /* Handler implementation... */
    return NGX_OK;
}

nginx.conf usage:

http {
    example_message "Global message";

    server {
        example_message "Server message";

        location /api {
            example;
            example_enable on;
            example_count 5;
            example_timeout 60s;
        }
    }
}