XT.PT Web servers → This story
News Web servers

nginx 1.31.5 open-sources the control API, and a variable can now pick the location

nginx 1.31.5 ships the control API (formerly NGINX Plus only), predicate locations, client_body_early_read and ngx_http_json_module, plus an HTTP/2 use-after-free fix.

https

nginx 1.31.5 mainline was released on September 2, 2026. The CHANGES file lists four features and a use-after-free fix, and each of the four features touches the part of nginx a configuration author lives in: how a request is matched to a location.

The control API leaves the subscription

The first line in CHANGES is "Feature: control API." What that means is spelled out on the command-line switches page, which documents a new -l switch:

-l unix:socket | port

The page describes it as enabling the "nginx control REST API" on a UNIX-domain socket or port, and adds a line of history: "Since version 1.29.8 and prior to version 1.31.5, this parameter was available as part of our commercial subscription."

The runtime control documentation says the API is "available since NGINX Plus PLS R37.0.0 LTS and NGINX Open Source 1.31.5" and lists what it exposes: GET /1/control/processes for worker process name, PID and exit state, GET /1/control/config for the in-memory configuration, PATCH /1/control/config to trigger a reload equivalent to nginx -s reload, and GET /1/nginx for version and build information. The reload returns its execution status in the HTTP response, which beats sending SIGHUP and then reading the error log.

Open-source builds need --with-control-api, and the documentation suggests checking for it with:

nginx -V 2>&1 | grep -- '--with-control-api'

There is no authentication. The documentation says "Never expose the Control API to the public Internet," and the release announcement on the community forum is blunter: "It is an unauthenticated interface to NGINX internals, and it does not belong on a network port." Bind it to a socket path only root can reach, or do not start it at all.

This is not the ngx_http_api_module of NGINX Plus, which remains subscription-only. The open-sourced piece is the master-process API: processes, config, reload.

Predicate locations

The second feature changes the location matching algorithm. The core module documentation now allows location $variable { ... } and defines it this way: "A predicate is specified with the preceding "$" and contains a variable evaluated during request processing. A predicate location matches if the variable value is not empty and is not equal to "0"."

The order matters. Prefix locations are checked first and the longest is remembered, then regular expressions in file order. The new step comes after those: "If no match with a regular expression is found, predicate locations are checked in the order of their appearance in the configuration file. If no predicate location matches, the configuration of the prefix location remembered earlier is used."

So a predicate never beats a regex, but it does beat the prefix fallback. Anything that can be a variable can be a predicate: a map on $http_user_agent, a geo block, a client certificate check. This is the job if inside location used to be bent to.

Reading the body before routing

client_body_early_read (context http and server) does what the name says. It "Enables reading of the client request body immediately after the request headers are received, using the request body read settings from the server block." It reads early if any of its string arguments is non-empty and not "0", so the trigger is typically a map on Content-Type. The documentation lists two incompatibilities: unbuffered-body modules such as ngx_http_grpc_module, and body-to-file modules such as ngx_http_dav_module.

The point of reading the body early is the fourth feature. ngx_http_json_module "extracts values from a JSON document stored in a variable and makes them available as variables." It is not built by default (--with-http_json_module), it has two directives, and one of them is a guardrail: json_max_depth defaults to 32 and accepts 1 to 256. The other is json_set $variable $source path. Put the three features together and a JSON-RPC style method field in the body can select the location that handles it, in C, with no njs or Lua.

The bugfix worth the upgrade on its own

Below the features, CHANGES records that a "use-after-free might occur in a worker process if proxying with buffering was used and an error occurred while sending the response to an HTTP/2 client." There is no advisory for it on the security advisories page, which lists nothing fixed in 1.31.5, but the release blog singles the fix out as recommended for anyone running with proxy_buffering on. Two further fixes cover workers that failed to exit after running out of file descriptors, and malformed FastCGI and uwsgi requests when a parameter name was too long. This is a mainline release.

Primary sources: nginx CHANGES, Command-line parameters, ngx_http_core_module, ngx_http_json_module, Runtime control (docs.nginx.com), NGINX 1.31.5 release blog, Community forum announcement, GitHub release-1.31.5, read 2026-09-11.

Corrections and source documents: contact the desk
Read next →
Read next
Runtimes · 4 min

Node.js 26.9.0 turns on node:ffi by default, six weeks before Node 26 becomes LTS

Recovery · 4 min

Windows 11 Cloud rebuild reaches the Beta channel: a full reinstall from WinRE, with drivers pulled from Windows Update