JS#
The module is used to implement handlers in njs — a subset of the JavaScript language.
In our repositories, the module is built
dynamically
and is available as a separate package named angie-module-njs or angie-pro-module-njs.
Note
A lightweight version of the package, named ...-njs-light, is also
available; however, it can't be used side by side with the regular one.
Configuration Example#
http {
js_import http.js;
js_set $foo http.foo;
js_set $summary http.summary;
js_set $hash http.hash;
resolver 10.0.0.1;
server {
listen 8000;
location / {
add_header X-Foo $foo;
js_content http.baz;
}
location = /summary {
return 200 $summary;
}
location = /hello {
js_content http.hello;
}
location = /fetch {
js_content http.fetch;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
location = /crypto {
add_header Hash $hash;
return 200;
}
}
}
The http.js file:
function foo(r) {
r.log("hello from foo() handler");
return "foo";
}
function summary(r) {
var a, s, h;
s = "JS summary\n\n";
s += "Method: " + r.method + "\n";
s += "HTTP version: " + r.httpVersion + "\n";
s += "Host: " + r.headersIn.host + "\n";
s += "Remote Address: " + r.remoteAddress + "\n";
s += "URI: " + r.uri + "\n";
s += "Headers:\n";
for (h in r.headersIn) {
s += " header '" + h + "' is '" + r.headersIn[h] + "'\n";
}
s += "Args:\n";
for (a in r.args) {
s += " arg '" + a + "' is '" + r.args[a] + "'\n";
}
return s;
}
function baz(r) {
r.status = 200;
r.headersOut.foo = 1234;
r.headersOut['Content-Type'] = "text/plain; charset=utf-8";
r.headersOut['Content-Length'] = 15;
r.sendHeader();
r.send("nginx");
r.send("java");
r.send("script");
r.finish();
}
function hello(r) {
r.return(200, "Hello world!");
}
async function fetch(r) {
let results = await Promise.all([ngx.fetch('https://example.com/'),
ngx.fetch('https://example.org/')]);
r.return(200, JSON.stringify(results, undefined, 4));
}
async function hash(r) {
let hash = await crypto.subtle.digest('SHA-512', r.headersIn.host);
r.setReturnValue(Buffer.from(hash).toString('hex'));
}
export default {foo, summary, baz, hello, fetch, hash};
Directives#
js_body_filter#
| |
Default | — |
location, if in location, limit_except |
Sets an njs function as a response body filter. The filter function is called for each data chunk of a response body with the following arguments:
| the HTTP request object |
| the incoming data chunk, may be a string or Buffer depending on the buffer_type value, by default is a string. |
| an object with the following properties:
- |
The filter function can pass its own modified version of the input data chunk to the next body filter by calling r.sendBuffer(). For example, to transform all the lowercase letters in the response body:
function filter(r, data, flags) {
r.sendBuffer(data.toLowerCase(), flags);
}
To stop filtering (following data chunks will be passed to client without calling js_body_filter), r.done() can be used.
If the filter function changes the length of the response body, then it is required to clear out the Content-Length response header (if any) in js_header_filter to enforce chunked transfer encoding.
Note
As the js_body_filter handler returns its result immediately, it supports only synchronous operations. Thus, asynchronous operations such as r.subrequest() or setTimeout() are not supported.
js_content#
Sets an njs function as a location content handler. Module functions can be referenced.
js_context_reuse#
Sets a maximum number of JS context to be reused for QuickJS engine. Each context is used for a single request. The finished context is put into a pool of reusable contexts. If the pool is full, the context is destroyed.
js_engine#
Sets a JavaScript engine to be used for njs scripts. The njs parameter sets the njs engine, also used by default. The qjs parameter sets the QuickJS engine.
js_fetch_buffer_size#
Sets the size of the buffer used for reading and writing with :ref:`Fetch API <ngx_fetch>`.
js_fetch_ciphers#
| |
Default |
|
http, server, location |
Specifies the enabled ciphers for HTTPS connections with Fetch API. The ciphers are specified in the format understood by the OpenSSL library.
The list of ciphers depends on the version of OpenSSL installed.
The full list can be viewed using the openssl ciphers command.
js_fetch_max_response_buffer_size#
| |
Default |
|
http, server, location |
Sets the maximum size of the response received with Fetch API.
js_fetch_protocols#
| |
Default |
|
http, server, location |
Enables the specified protocols for HTTPS connections with Fetch API.
js_fetch_timeout#
Defines a timeout for reading and writing for Fetch API. The timeout is set only between two successive read/write operations, not for the whole response. If no data is transmitted within this time, the connection is closed.
js_fetch_trusted_certificate#
Specifies a file with trusted CA certificates in the PEM format used to verify the HTTPS certificate with Fetch API.
js_fetch_verify#
Enables or disables verification of the HTTPS server certificate with Fetch API.
js_fetch_verify_depth#
Sets the verification depth in the HTTPS server certificates chain with Fetch API.
js_fetch_keepalive#
Activates the cache for connections to destination servers. When the value is greater than 0, enables keepalive connections for Fetch API.
The connections parameter sets the maximum number of idle keepalive connections to destination servers that are preserved in the cache of each worker process. When this number is exceeded, the least recently used connections are closed.
Example:
location /fetch {
js_fetch_keepalive 32;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
js_content main.fetch_handler;
}
js_fetch_keepalive_requests#
| |
Default |
|
http, server, location |
Sets the maximum number of requests that can be served through one keepalive connection with Fetch API. After the maximum number of requests is made, the connection is closed.
Closing connections periodically is necessary to free per-connection memory allocations. Therefore, using too high maximum number of requests could result in excessive memory usage and not recommended.
js_fetch_keepalive_time#
Limits the maximum time during which requests can be processed through one keepalive connection with Fetch API. After this time is reached, the connection is closed following the subsequent request processing.
js_fetch_keepalive_timeout#
| |
Default |
|
http, server, location |
Sets a timeout during which an idle keepalive connection to a destination server will stay open with Fetch API.
js_header_filter#
| |
Default | — |
location, if in location, limit_except |
Sets an njs function as a response header filter. The directive allows changing arbitrary header fields of a response header.
Note
As the js_header_filter handler returns its result immediately, it supports only synchronous operations. Thus, asynchronous operations such as r.subrequest() or setTimeout() are not supported.
js_import#
Imports a module that implements location and variable handlers in njs. The export_name is used as a namespace to access module functions. If the export_name is not specified, the module name will be used as a namespace.
js_import http.js;
Here, the module name http is used as a namespace while accessing
exports. If the imported module exports foo(), http.foo is used
to refer to it.
Several js_import directives can be specified.
js_path#
Sets an additional path for njs modules.
js_periodic#
| |
Default | — |
location |
Specifies a content handler to run at regular interval. The handler receives a session object as its first argument, it also has access to global objects such as ngx.
The optional interval parameter sets the interval between two consecutive runs, by default, 5 seconds.
The optional jitter parameter sets the time within which the location content handler will be randomly delayed, by default, there is no delay.
By default, the js_handler is executed on worker process 0. The optional worker_affinity parameter allows specifying particular worker processes where the location content handler should be executed. Each worker process set is represented by a bitmask of allowed worker processes. The all mask allows the handler to be executed in all worker processes.
Example:
example.conf:
location @periodics {
# to be run at 1 minute intervals in worker process 0
js_periodic main.handler interval=60s;
# to be run at 1 minute intervals in all worker processes
js_periodic main.handler interval=60s worker_affinity=all;
# to be run at 1 minute intervals in worker processes 1 and 3
js_periodic main.handler interval=60s worker_affinity=0101;
resolver 10.0.0.1;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
example.js:
async function handler(s) {
let reply = await ngx.fetch('https://example.com/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}
js_preload_object#
Preloads an immutable object at configure time. The name is used as a name of the global variable though which the object is available in njs code. If the name is not specified, the file name will be used instead.
js_preload_object map.json;
Here, the map is used as a name while accessing the preloaded object.
Several js_preload_object directives can be specified.
js_set#
Sets an njs function for the specified variable. Module functions can be referenced.
The function is called when the variable is referenced for the first time for a given request. The exact moment depends on a phase at which the variable is referenced. This can be used to perform some logic not related to variable evaluation. For example, if the variable is referenced only in the log_format directive, its handler will not be executed until the log phase. This handler can be used to do some cleanup right before the request is freed.
Since njs 0.8.6, if an optional argument nocache is specified, the handler is called every time it is referenced. Due to current limitations of the rewrite module, when a nocache variable is referenced by the set directive its handler should always return a fixed-length value.
Note
As the js_set handler returns its result immediately, it supports only synchronous callbacks. Thus, asynchronous callbacks such as r.subrequest() or setTimeout() are not supported.
js_var#
Declares a writable variable. The value can contain text, variables, and their combination. The variable is not overwritten after a redirect, unlike variables created with the set directive.
Request Argument#
Each HTTP njs handler receives one argument, a request object.