Summer’s gone, so it’s time to forfeit the halcyon tranquility and get some working attitude on. The NGINX Unit team has recently presented our first two‑digit version, NGINX Unit 1.10.0; let’s page through the recent developments and shed some light on our plans for the future.
Routing Advancements
In our two latest releases, some major effort went into extending the request routing capabilities that were initially introduced in NGINX Unit 1.8.0. Version 1.9.0 included essential support for arguments, headers, and cookies in matching clauses, whereas NGINX Unit 1.10.0 added scheme‑based routing to the mix. A few examples:
"match": {
"host": "www.example.com",
"arguments": {
"mode": ["mobile", "desktop"],
"ui": "!full"
}
}
This condition matches queries like www.example.com/?mode=mobile and www.example.com/?mode=desktop&ui=compact, but not www.example/com/?mode=desktop&ui=full.
"match": {
"headers": [
{
"Accept-Encoding": "*gzip*",
"User-Agent": "Mozilla/5.0*"
},
{
"User-Agent": "curl*"
}
]
}
This clause matches only requests where the User-Agent
header is either Mozilla/5.0
(and gzip
compression is also applied) or curl
.
"match": {
"host": "example.com",
"scheme": "https"
}
This condition matches https://example.com, but not http://example.com.
Pattern matching was also extended to allow wildcards in the middle of the match string:
"match": {
"host": ["eu-*.example.com", "!eu-5.example.com"]
}
This clause happily matches all eu- subdomains of example.com except eu-5.example.com.
Configuration Updates
The config API received some polishing as well. Most importantly, it now supports non‑idempotent POST
semantics. In less fancy terms, this means you can append new items to arrays, which do occur in NGINX Unit configuration. For instance, consider this sample output from a curl
query to NGINX Unit’s control socket:
# curl --unix-socket /path/to/control.unit.sock http://localhost/config/
{
"listeners": {
"*:8000": {
"pass": "routes"
}
},
"applications": {
"blogs": {
"type": "python",
"module": "wsgi",
"path": "/www/blogs/"
}
},
"routes": [
{
"match": {
"host": [
"dev1.example.com",
"dev2.example.com"
]
},
"action": {
"pass": "applications/blogs"
}
}
]
}
Let’s decipher the JSON: the configuration includes an application called blogs
, a routes
section that allows access to the app via two hostnames, and a listener that passes incoming requests through the routing engine. Using the POST
method, we append a new hostname to the host
array:
# curl -X POST -d '"dev3.example.com"' --unix-socket=/path/to/control.unit.sock \
http://localhost/config/routes/0/match/host/
{
"success": "Reconfiguration done."
}
Note that all responses from NGINX Unit are also encoded in JSON. Next, I make a curl
query to display just the routes
section:
# curl --unix-socket /path/to/control.unit.sock http://localhost/config/routes/
[
{
"match": {
"host": [
"dev1.example.com",
"dev2.example.com",
"dev3.example.com"
]
},
"action": {
"pass": "applications/blogs"
}
}
]
As you can see, the POST
operation appended its payload to the end of the host
array. It’s worth mentioning here that NGINX Unit changes only the sections of the configuration that are affected by the update, calculating the difference between the old config and the new on the fly to minimize overhead. Handy!
In other news, we’ve also done away with a few nasty bugs, making config manipulation more reliable.
Application Languages
Most of the latest changes in language support are for Node.js, including a new built‑in WebSocket server implementation in NGINX Unit 1.10.0. To use it, just specify our module as the parameter to the require
function instead of the native websocket
module:
var webSocketServer = require('unit-http/websocket').server;
In addition, NGINX Unit 1.10.0 adds some axle grease to improve integration with the latest Node.js versions; a few compatibility bugs were fixed as well.
Another significant update to language support is the PHP module’s new ability to parse request URIs into the PATH_INFO
environment variable – something many PHP developers have come to rely on. The change might appear tiny, but it makes it easier to run some major apps like NextCloud, as detailed in the shiny new how‑to we’ve provided for your convenience. Oh, and speaking of…
Documentation
Our documentation has been extended significantly in the last few months with various guides and how‑tos in response to your insightful queries, friendly GitHub rants, and reasonable – but misplaced – assumptions about how some features work.
Some of the major updates include a guide to running NGINX Unit in Docker that is accompanied by a sample Dockerfile for each of the supported languages, an end-to-end guide on language module manipulation, and how‑tos for popular apps and frameworks like Catalyst and Redmine (along with the aforementioned NextCloud). There’s more to come – please check the docs once in a while or post your “gotta see this app run on NGINX Unit” ideas on GitHub.
Conclusion
The journey continues, and NGINX Unit is gaining momentum. Our team is steadily growing with new people bringing new ideas, so follow us for more exciting news (which we already have in the works): see the recent updates in the changelog or monitor our GitHub repository to join the discussions and development.
Finally, a few words about future updates. At this moment, we are working hard to bring to life such long‑promised features as WebSocket support for Java, serving static assets, and proxying. Our team is quite serious about making NGINX Unit a really busy little web engine. Stay tuned!
Interested in becoming a full‑time engineer for NGINX? Check our job board.
NGINX Plus subscribers get support for NGINX Unit at no additional charge. Start a free 30‑day trial of NGINX Plus today.