Open-Source Wikis

/

nginx

/

Primitives

/

Request (`ngx_http_request_t`)

nginx/nginx

Request (ngx_http_request_t)

Active contributors: Maxim Dounin, Sergey Kandaurov, Roman Arutyunyan

What it is

ngx_http_request_t is the per-HTTP-request state struct: parsed request line, headers, body state, the request pool, the chosen server and location configs, the variable values, the upstream subrequest pointer, the chosen content handler, the postponed-output queue for subrequests, and dozens of flags. Every HTTP/1.1, HTTP/2, and HTTP/3 request creates exactly one ngx_http_request_t.

src/http/ngx_http_request.h is the canonical reference — at ~22 KB, one of the largest header files in the codebase.

High-level layout

The struct has the following groups (selectively summarized):

struct ngx_http_request_s {
    uint32_t                          signature;       /* "HTTP" */
    ngx_connection_t                 *connection;
    void                            **ctx;             /* per-module context */
    void                            **main_conf;
    void                            **srv_conf;
    void                            **loc_conf;
    ngx_http_event_handler_pt         read_event_handler;
    ngx_http_event_handler_pt         write_event_handler;

    /* upstream */
    ngx_http_upstream_t              *upstream;
    ngx_array_t                      *upstream_states;

    /* memory */
    ngx_pool_t                       *pool;
    ngx_buf_t                        *header_in;

    /* parsed request line */
    ngx_http_headers_in_t             headers_in;
    ngx_http_headers_out_t            headers_out;
    ngx_http_request_body_t          *request_body;

    time_t                            lingering_time;
    time_t                            start_sec;
    ngx_msec_t                        start_msec;

    ngx_uint_t                        method;
    ngx_uint_t                        http_version;

    ngx_str_t                         request_line;
    ngx_str_t                         uri;
    ngx_str_t                         args;
    ngx_str_t                         exten;
    ngx_str_t                         unparsed_uri;
    ngx_str_t                         method_name;
    ngx_str_t                         http_protocol;
    ngx_str_t                         schema;

    ngx_chain_t                      *out;
    ngx_http_request_t               *main;            /* root request */
    ngx_http_request_t               *parent;          /* parent of subrequest */
    ngx_http_postponed_request_t     *postponed;
    ngx_http_post_subrequest_t       *post_subrequest;
    ngx_http_posted_request_t        *posted_requests;

    ngx_int_t                         phase_handler;   /* current phase index */
    ngx_http_handler_pt               content_handler;
    ngx_uint_t                        access_code;

    ngx_http_variable_value_t        *variables;       /* indexed cache */

    /* ... ~80 bit-fields for flags ... */
    unsigned                          internal:1;
    unsigned                          subrequest_in_memory:1;
    unsigned                          waited:1;
    /* ... etc ... */

    ngx_http_cache_t                 *cache;

    ngx_http_log_handler_pt           log_handler;
    ngx_http_cleanup_t               *cleanup;

    unsigned                          count:16;
    /* ... */
    unsigned                          done:1;
    unsigned                          aio:1;

    ngx_uint_t                        gzip_vary;       /* gzip-related */
    ngx_uint_t                        gzip_ok;
};

(Edited for length; see src/http/ngx_http_request.h for everything.)

Lifecycle

Created in ngx_http_create_request(c) (src/http/ngx_http_request.c):

  1. Allocate a new pool sized by client_header_pool_size.
  2. Allocate the request struct from the pool.
  3. Fill r->signature = "HTTP", r->connection = c, r->main = r (main request), r->count = 1.
  4. Set up r->ctx (per-module pointer array).
  5. Set the connection's read handler to ngx_http_process_request_line.

The read handler reads bytes, calls ngx_http_parse_request_line, then ngx_http_process_request_headers, then dispatches into the phase engine. See systems/http/request-lifecycle.

Destroyed in ngx_http_finalize_requestngx_http_close_requestngx_http_free_request:

  • Run the request-cleanup chain (r->cleanup).
  • If we're keeping the connection (HTTP keep-alive), arm the wait handler and return.
  • Otherwise, call ngx_close_connection(c).

r->main, r->parent, subrequests

r->main is the root of the request tree. Each subrequest has its own ngx_http_request_t with r->parent pointing at the immediate parent and r->main always pointing at the original request. The main request's count field is the total number of in-flight sub+main; ngx_http_finalize_request(r, NGX_DONE) decrements it.

The postpone filter (ngx_http_postpone_filter_module) walks r->postponed to interleave subrequest output in the order the application produced subrequests, regardless of the order responses come back.

r->ctx

A void ** indexed by HTTP module index. Modules use ngx_http_set_ctx(r, ctx, ngx_http_my_module) and ngx_http_get_module_ctx(r, ngx_http_my_module) to attach per-request state. The array is sized at config-parse time based on ngx_http_max_module.

Headers

r->headers_in.headers is a ngx_list_t of ngx_table_elt_t (key/value pairs). Common headers are also pulled out as direct pointers (r->headers_in.host, r->headers_in.user_agent, r->headers_in.content_length, etc.). The HTTP parser fills these as it goes.

r->headers_out is the same but for the response, including status (r->headers_out.status), content type, content length, and a headers list. The header filter chain reads r->headers_out and serializes it.

The variable cache

r->variables is an array of ngx_http_variable_value_t, one per registered variable, indexed by the variable's index (assigned at config time). Lookups go through ngx_http_get_indexed_variable(r, idx):

  • If r->variables[idx].valid, return the cached value.
  • Otherwise call the variable's get_handler, cache the result, return.

This is the fast path. The slow path is ngx_http_get_variable by name, which does a hash lookup.

Phase index

r->phase_handler is the index into the flat phase-handler array (ngx_http_phase_engine_t.handlers). Phase handlers return:

  • NGX_OK — done with this request, finalize
  • NGX_DECLINED — try next handler in same phase
  • NGX_AGAIN / NGX_DONE — async, will resume later

The engine increments r->phase_handler to advance.

Cleanup

r->cleanup is a chain of ngx_http_cleanup_t nodes (similar to pool cleanups but specifically for request lifecycle). Modules register handlers that fire when the request finalizes:

ngx_http_cleanup_t  *cln = ngx_http_cleanup_add(r, sizeof(my_state_t));
cln->handler = my_cleanup_handler;

These run in LIFO order at finalize time, before the pool is destroyed. Used for, e.g., closing files, releasing locks in shared zones, removing entries from per-request rbtrees.

Pitfalls

  • r->count is essential — touching it manually is almost always wrong. Use ngx_http_subrequest/ngx_http_finalize_request.
  • r->pool outlives the connection for some lingering_close paths. Don't allocate from c->pool and assume it survives until request finalize.
  • Subrequests share c but not r — be careful which one you log against.
  • HTTP/2 and HTTP/3 streams bypass ngx_http_create_request's reading code — they construct the request directly from frame parsers. Hot-path code that reads r->header_in should not assume it's populated for H2/H3.

Cross-references

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

Request (`ngx_http_request_t`) – nginx wiki | Factory