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):
- Allocate a new pool sized by
client_header_pool_size. - Allocate the request struct from the pool.
- Fill
r->signature = "HTTP",r->connection = c,r->main = r(main request),r->count = 1. - Set up
r->ctx(per-module pointer array). - 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_request → ngx_http_close_request → ngx_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, finalizeNGX_DECLINED— try next handler in same phaseNGX_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->countis essential — touching it manually is almost always wrong. Usengx_http_subrequest/ngx_http_finalize_request.r->pooloutlives the connection for somelingering_closepaths. Don't allocate fromc->pooland assume it survives until request finalize.- Subrequests share
cbut notr— 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 readsr->header_inshould not assume it's populated for H2/H3.
Cross-references
- systems/http/request-lifecycle — the phase engine that walks
r->phase_handler - systems/http/upstream —
r->upstream - systems/http/variables-and-scripts —
r->variables - primitives/connection —
r->connection - primitives/pool —
r->pool
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.