Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Mount of the Nginx handler module


May 23, 2021 Nginx Getting started


Table of contents


The mount of the handler module

The real handler function of the handler module is mounted to the process in two ways, one way is to mount according to the processing stage; Another way to mount is to mount on demand.

Mount by processing stage

In order to have more granular control over the processing of client requests, Nginx divides this process into 11 phases. From front to back, they are listed as follows:

  • NGX_HTTP_POST_READ_PHASE: Read the request content stage
  • NGX_HTTP_SERVER_REWRITE_PHASE: Server requests address override phase
  • NGX_HTTP_FIND_CONFIG_PHASE: Configure the lookup phase:
  • NGX_HTTP_REWRITE_PHASE: Location requests address rewrite phase
  • NGX_HTTP_POST_REWRITE_PHASE: Request an address to rewrite the commit phase
  • NGX_HTTP_PREACCESS_PHASE: Access check preparation phase
  • NGX_HTTP_ACCESS_PHASE: Access check phase
  • NGX_HTTP_POST_ACCESS_PHASE: Access checks the submission phase
  • NGX_HTTP_TRY_FILES_PHASE: Configure items try_files processing phase
  • NGX_HTTP_CONTENT_PHASE: Content generation phase
  • NGX_HTTP_LOG_PHASE: Log module processing phase

In general, most of our custom modules are mounted in the NGX_HTTP_CONTENT_PHASE stage. Mounted actions are typically in postconfiguration functions called in the context of a module.

Note: There are several stages that are special, and it doesn't call any handler mounted, which means you don't have to mount to these stages:

  • NGX_HTTP_FIND_CONFIG_PHASE
  • NGX_HTTP_POST_ACCESS_PHASE
  • NGX_HTTP_POST_REWRITE_PHASE
  • NGX_HTTP_TRY_FILES_PHASE

So there are actually 7 phases you can go to mount handler.

The mount code is as follows (excerpted from hello module):

    static ngx_int_t
    ngx_http_hello_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_CONTENT_PHASE].handlers);
        if (h == NULL) {
            return NGX_ERROR;
        }

        *h = ngx_http_hello_handler;

        return NGX_OK;
    }

Handler mounted in this manner is also known as content phase handlers.

Mount on demand

Handler mounted in this way is also known as content handler.

When a request comes in, Nginx executes all handlers in each stage, starting with the NGX_HTTP_POST_READ_PHASE stage in the next phase. W hen you NGX_HTTP_CONTENT_PHASE to the contenter phase, if the location has a corresponding content handler module, then execute the real handler of the content handler module. Otherwise, continue to execute NGX_HTTP_CONTENT_PHASE content phase handlers in turn until a function process returns NGX_OK or NGX_ERROR.

In other words, if there is a content handler module when a location is processed to the NGX_HTTP_CONTENT_PHASE stage, all content phase handlers mounted on the NGX_HTTP_CONTENT_PHASE will not be executed.

But handler mounted using this method has a feature that must be NGX_HTTP_CONTENT_PHASE stage to execute. If you want your handler to execute at an earlier stage, don't use this mount.

So in what cases will you use this way to mount it? In general, when a module processes a location and finds that it conforms to the logic of its own processing, and there is no need to call the other handler in the NGX_HTTP_CONTENT_PHASE phase for processing, the handler is dynamically mounted.

Here's a look at a specific example of using this mounting method (from Emiller's Guide To Nginx Module Development).

    static char *
    ngx_http_circle_gif(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_circle_gif_handler;

        return NGX_CONF_OK;
    }