<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../../dtd/module.dtd">
<module name="Module ngx_http_js_module"
link="/en/docs/http/ngx_http_js_module.html"
lang="en"
rev="62">
<section id="summary">
<para>
The <literal>ngx_http_js_module</literal> module is used to implement
location and variable handlers
in <link doc="../njs/index.xml">njs</link> —
a subset of the JavaScript language.
</para>
<para>
Download and install instructions are available
<link doc="../njs/install.xml">here</link>.
</para>
</section>
<section id="example" name="Example Configuration">
<para>
The example works since
<link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>.
<example>
http {
# since 0.9.1
js_engine qjs;
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;
}
# since 0.7.0
location = /fetch {
js_content http.fetch;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
# since 0.7.0
location = /crypto {
add_header Hash $hash;
return 200;
}
}
}
</example>
</para>
<para>
The <path>http.js</path> file:
<example>
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!");
}
// since 0.7.0
async function fetch(r) {
let results = await Promise.all([ngx.fetch('https://nginx.org/'),
ngx.fetch('https://nginx.org/en/')]);
r.return(200, JSON.stringify(results, undefined, 4));
}
// since 0.7.0
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};
</example>
</para>
</section>
<section id="directives" name="Directives">
<directive name="js_body_filter">
<syntax><value>module.function</value>
[<value>buffer_type</value>=<value>string</value> | <value>buffer</value>]</syntax>
<default/>
<context>location</context>
<context>if in location</context>
<context>limit_except</context>
<appeared-in>0.5.2</appeared-in>
<para>
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:
<list type="tag">
<tag-name><literal>r</literal></tag-name>
<tag-desc>
the <link doc="../njs/reference.xml" id="http">HTTP request</link> object
</tag-desc>
<tag-name><literal>data</literal></tag-name>
<tag-desc>
the incoming data chunk,
may be a string or Buffer
depending on the <literal>buffer_type</literal> value,
by default is a string.
Since <link doc="../njs/changes.xml" id="njs0.8.5">0.8.5</link>, the
<literal>data</literal> value is implicitly converted to a valid UTF-8 string
by default.
For binary data, the <literal>buffer_type</literal> value
should be set to <literal>buffer</literal>.
</tag-desc>
<tag-name><literal>flags</literal></tag-name>
<tag-desc>
an object with the following properties:
<list type="tag">
<tag-name><literal>last</literal></tag-name>
<tag-desc>
a boolean value, true if data is a last buffer.
</tag-desc>
</list>
</tag-desc>
</list>
</para>
<para>
The filter function can pass its own modified version
of the input data chunk to the next body filter by calling
<link doc="../njs/reference.xml" id="r_sendbuffer"><literal>r.sendBuffer()</literal></link>.
For example, to transform all the lowercase letters in the response body:
<example>
function filter(r, data, flags) {
r.sendBuffer(data.toLowerCase(), flags);
}
</example>
</para>
<para>
If the filter function changes the length of the response body, the
<header>Content-Length</header> response header (if present) should be cleared
in <link id="js_header_filter"><literal>js_header_filter</literal></link>
to enforce chunked transfer encoding:
<example>
example.conf:
location /foo {
# proxy_pass http://localhost:8080;
js_header_filter main.clear_content_length;
js_body_filter main.filter;
}
example.js:
function clear_content_length(r) {
delete r.headersOut['Content-Length'];
}
</example>
</para>
<para>
To stop filtering and pass the data chunks to the client
without calling <literal>js_body_filter</literal>,
<link doc="../njs/reference.xml" id="r_done"><literal>r.done()</literal></link>
can be used.
For example, to prepend some data to the response body:
<example>
function prepend(r, data, flags) {
r.sendBuffer("XXX");
r.sendBuffer(data, flags);
r.done();
}
</example>
</para>
<para>
<note>
As the <literal>js_body_filter</literal> handler
returns its result immediately, it supports
only synchronous operations.
Thus, asynchronous operations such as
<link doc="../njs/reference.xml" id="r_subrequest">r.subrequest()</link>
or
<link doc="../njs/reference.xml" id="settimeout">setTimeout()</link>
are not supported.
</note>
</para>
<para>
<note>
The directive can be specified inside the
<link doc="../http/ngx_http_rewrite_module.xml" id="if">if</link> block
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
<directive name="js_access">
<syntax><value>module.function</value></syntax>
<default/>
<context>location</context>
<context>if in location</context>
<context>limit_except</context>
<appeared-in>0.9.9</appeared-in>
<para>
Sets an njs function as a handler in the
<link doc="../dev/development_guide.xml" id="http_phases">access phase</link>.
Asynchronous operations such as
<link doc="../njs/reference.xml" id="r_subrequest">r.subrequest()</link>,
<link doc="../njs/reference.xml" id="ngx_fetch">ngx.fetch()</link>,
and <link doc="../njs/reference.xml" id="settimeout">setTimeout()</link>
are supported.
</para>
<para>
A handler that returns without calling
<link doc="../njs/reference.xml" id="r_return"><literal>r.return()</literal></link>
or
<link doc="../njs/reference.xml" id="r_decline"><literal>r.decline()</literal></link>
grants access.
To deny access or send a custom response (for example, a redirect),
the handler may call
<link doc="../njs/reference.xml" id="r_return"><literal>r.return()</literal></link>.
To make the handler express no opinion, deferring the decision to other
access checkers under
<link doc="ngx_http_core_module.xml" id="satisfy"><literal>satisfy any</literal></link>,
the handler may call
<link doc="../njs/reference.xml" id="r_decline"><literal>r.decline()</literal></link>.
</para>
<para>
For example:
<example>
example.conf:
location /protected/ {
js_access main.auth;
proxy_pass http://upstream;
}
example.js:
async function auth(r) {
let reply = await ngx.fetch('http://authsvc/check', {
headers: {Authorization: r.headersIn.Authorization}
});
if (reply.status != 200) {
r.return(401);
return;
}
}
export default {auth};
</example>
</para>
</directive>
<directive name="js_content">
<syntax><value>module.function</value></syntax>
<default/>
<context>location</context>
<context>if in location</context>
<context>limit_except</context>
<para>
Sets an njs function as a location content handler.
Since <link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>,
a module function can be referenced.
</para>
<para>
<note>
The directive can be specified inside the
<link doc="../http/ngx_http_rewrite_module.xml" id="if">if</link> block
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
<directive name="js_context_reuse">
<syntax><value>number</value></syntax>
<default>128</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.8.6</appeared-in>
<para>
Sets a maximum number of JS context to be reused for
<link doc="../njs/engine.xml">QuickJS engine</link>.
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.
</para>
</directive>
<directive name="js_engine">
<syntax><literal>njs</literal> | <literal>qjs</literal></syntax>
<default>njs</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.8.6</appeared-in>
<para>
Sets a <link doc="../njs/engine.xml">JavaScript engine</link>
to be used for njs scripts.
The <literal>njs</literal> parameter sets the njs engine, also used by default.
The <literal>qjs</literal> parameter sets the QuickJS engine.
</para>
<para>
<note>
The <literal>njs</literal> engine is deprecated
since <link doc="../njs/changes.xml" id="njs1.0.0">1.0.0</link>;
new configurations should use the <literal>qjs</literal>
(<link doc="../njs/engine.xml" id="quickjs_engine">QuickJS</link>) engine.
</note>
</para>
</directive>
<directive name="js_fetch_buffer_size">
<syntax><value>size</value></syntax>
<default>16k</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.4</appeared-in>
<para>
Sets the <value>size</value> of the buffer used for reading and writing
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_fetch_ciphers">
<syntax><value>ciphers</value></syntax>
<default>HIGH:!aNULL:!MD5</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.0</appeared-in>
<para>
Specifies the enabled ciphers for HTTPS requests
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
The ciphers are specified in the format understood by the
OpenSSL library.
</para>
<para>
The full list can be viewed using the
“<command>openssl ciphers</command>” command.
</para>
</directive>
<directive name="js_fetch_max_response_buffer_size">
<syntax><value>size</value></syntax>
<default>1m</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.4</appeared-in>
<para>
Sets the maximum <value>size</value> of the response received
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_fetch_protocols">
<syntax>
[<literal>TLSv1</literal>]
[<literal>TLSv1.1</literal>]
[<literal>TLSv1.2</literal>]
[<literal>TLSv1.3</literal>]</syntax>
<default>TLSv1 TLSv1.1 TLSv1.2</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.0</appeared-in>
<para>
Enables the specified protocols for HTTPS requests
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_fetch_timeout">
<syntax><value>time</value></syntax>
<default>60s</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.4</appeared-in>
<para>
Defines a timeout for reading and writing
for <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
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.
</para>
</directive>
<directive name="js_fetch_trusted_certificate">
<syntax><value>file</value></syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.0</appeared-in>
<para>
Specifies a <value>file</value> with trusted CA certificates in the PEM format
used to
<link doc="../njs/reference.xml" id="fetch_verify">verify</link>
the HTTPS certificate
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_fetch_verify">
<syntax><literal>on</literal> | <literal>off</literal></syntax>
<default>on</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.4</appeared-in>
<para>
Enables or disables verification of the HTTPS server certificate
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_fetch_verify_depth">
<syntax><value>number</value></syntax>
<default>100</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.0</appeared-in>
<para>
Sets the verification depth in the HTTPS server certificates chain
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_fetch_proxy">
<syntax><value>url</value></syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.9.4</appeared-in>
<para>
Configures a forward proxy URL
with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
The <value>url</value> supports the HTTP scheme only
and can contain optional user credentials
in the format <literal>http://[user:password@]host:port</literal>
for Basic authentication.
Supports both HTTP and HTTPS connections to destination servers.
If the <value>url</value> is empty, proxy routing is disabled.
The parameter value can contain variables.
</para>
<para>
Example:
<example>
location /fetch {
js_fetch_proxy http://user:[email protected]:3128;
js_content main.fetch_handler;
}
</example>
</para>
</directive>
<directive name="js_fetch_keepalive">
<syntax><value>connections</value></syntax>
<default>0</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.9.2</appeared-in>
<para>
Activates the cache for connections to destination servers.
When the value is greater than <literal>0</literal>,
enables keepalive connections for
<link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
<para>
The <value>connections</value> 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.
</para>
<para>
In HTTP, the cache is maintained separately for each effective location
configuration. A value set at the <literal>http</literal> or
<literal>server</literal> level is inherited by locations, but each location
uses its own cache.
Cached connections are reused for requests with the same protocol, host,
and port.
</para>
<para>
When enabled, keepalive assumes that destination servers send valid HTTP
responses.
</para>
<para>
Example:
<example>
location /fetch {
js_fetch_keepalive 32;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
js_content main.fetch_handler;
}
</example>
</para>
</directive>
<directive name="js_fetch_keepalive_requests">
<syntax><value>number</value></syntax>
<default>1000</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.9.2</appeared-in>
<para>
Sets the maximum number of requests that can be served through one keepalive
connection with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
After the maximum number of requests is made, the connection is closed.
</para>
<para>
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.
</para>
</directive>
<directive name="js_fetch_keepalive_time">
<syntax><value>time</value></syntax>
<default>1h</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.9.2</appeared-in>
<para>
Limits the maximum time during which requests can be processed through one
keepalive connection with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
After this time is reached, the connection is closed following the subsequent
request processing.
</para>
</directive>
<directive name="js_fetch_keepalive_timeout">
<syntax><value>time</value></syntax>
<default>60s</default>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.9.2</appeared-in>
<para>
Sets a timeout during which an idle keepalive connection to a destination server
will stay open with <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>
</directive>
<directive name="js_header_filter">
<syntax><value>module.function</value></syntax>
<default/>
<context>location</context>
<context>if in location</context>
<context>limit_except</context>
<appeared-in>0.5.1</appeared-in>
<para>
Sets an njs function as a response header filter.
The directive allows changing arbitrary header fields of a response header.
</para>
<para>
<note>
As the <literal>js_header_filter</literal> handler
returns its result immediately, it supports
only synchronous operations.
Thus, asynchronous operations such as
<link doc="../njs/reference.xml" id="r_subrequest">r.subrequest()</link>
or
<link doc="../njs/reference.xml" id="settimeout">setTimeout()</link>
are not supported.
</note>
</para>
<para>
<note>
The directive can be specified inside the
<link doc="../http/ngx_http_rewrite_module.xml" id="if">if</link> block
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
<directive name="js_import">
<syntax><value>module.js</value> |
<value>export_name from module.js</value></syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.4.0</appeared-in>
<para>
Imports a module that implements location and variable handlers in njs.
The <literal>export_name</literal> is used as a namespace
to access module functions.
If the <literal>export_name</literal> is not specified,
the module name will be used as a namespace.
<example>
js_import http.js;
</example>
Here, the module name <literal>http</literal> is used as a namespace
while accessing exports.
If the imported module exports <literal>foo()</literal>,
<literal>http.foo</literal> is used to refer to it.
</para>
<para>
Several <literal>js_import</literal> directives can be specified.
</para>
<para>
When <literal>js_import</literal> is specified inside a
<link doc="ngx_http_core_module.xml" id="location"/>,
the imported modules are visible only if no JavaScript code
has been invoked earlier in the request.
A single VM is created per request when a
<link id="js_set"/> variable is first accessed
or when a <link id="js_content"/>, <link id="js_header_filter"/>,
<link id="js_body_filter"/>, or <link id="js_access"/> handler
is first invoked.
The VM is cloned from the configuration scope active at that moment,
and all subsequent JavaScript invocations within the request reuse it.
Thus, if any of the above is referenced before the request is mapped
to its final location, for example from a server-level
<link doc="ngx_http_rewrite_module.xml" id="set"/>,
the VM is bound to the import set of the outer scope, and modules
imported in the matched <literal>location</literal> will not be visible.
To avoid this, declare such imports in a common parent scope.
</para>
<para>
<note>
The directive can be specified on the
<literal>server</literal> and <literal>location</literal> level
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
<directive name="js_include">
<syntax><value>file</value></syntax>
<default/>
<context>http</context>
<para>
Specifies a file that implements location and variable handlers in njs:
<example>
nginx.conf:
js_include http.js;
location /version {
js_content version;
}
http.js:
function version(r) {
r.return(200, njs.version);
}
</example>
</para>
<para>
The directive was made obsolete in version
<link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>
and was removed in version
<link doc="../njs/changes.xml" id="njs0.7.1">0.7.1</link>.
The <link id="js_import"/> directive should be used instead.
</para>
</directive>
<directive name="js_load_http_native_module">
<syntax><value>path</value> [<literal>as</literal> <value>name</value>]</syntax>
<default/>
<context>main</context>
<appeared-in>0.9.5</appeared-in>
<para>
Loads a <link doc="../njs/native_modules.xml">native module</link>
(shared library) for use in HTTP JavaScript code.
The directive is
<link doc="../njs/engine.xml" id="quickjs_engine">QuickJS</link>-only
and is not available when using the njs built-in JavaScript engine.
</para>
<para>
The <value>path</value> parameter
specifies the absolute path to the shared library file.
The optional <literal>as</literal> <value>name</value> parameter
provides an alias name for importing the module in JavaScript code.
If not specified, the module can be imported using its filename.
</para>
<para>
Example:
<example>
js_load_http_native_module /path/to/mylib.so;
js_load_http_native_module /path/to/other.so as myalias;
http {
js_import main.js;
# ... rest of http configuration
}
</example>
In JavaScript code:
<example>
// Import by filename
import * as mylib from 'mylib.so';
// Import by alias
import * as myalias from 'myalias';
// Use exported functions
let result = mylib.add(5, 10);
</example>
</para>
<para>
<note>
For security reasons, this directive is only allowed
in the <literal>main</literal> configuration context.
Native modules run with full process privileges;
use absolute paths and ensure proper code review.
</note>
</para>
</directive>
<directive name="js_path">
<syntax>
<value>path</value></syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.3.0</appeared-in>
<para>
Sets an additional path for njs modules.
</para>
<para>
<note>
The directive can be specified on the
<literal>server</literal> and <literal>location</literal> level
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
<directive name="js_periodic">
<syntax><value>module.function</value>
[<literal>interval</literal>=<value>time</value>]
[<literal>jitter</literal>=<value>number</value>]
[<literal>worker_affinity</literal>=<value>mask</value>]</syntax>
<default/>
<context>location</context>
<appeared-in>0.8.1</appeared-in>
<para>
Specifies a content handler to run at regular interval.
The handler receives a
<link doc="../njs/reference.xml" id="periodic_session">session object</link>
as its first argument,
it also has access to global objects such as
<link doc="../njs/reference.xml" id="ngx">ngx</link>.
</para>
<para>
The optional <literal>interval</literal> parameter
sets the interval between two consecutive runs,
by default, 5 seconds.
</para>
<para>
The optional <literal>jitter</literal> parameter sets the time within which
the location content handler will be randomly delayed,
by default, there is no delay.
</para>
<para>
By default, the <literal>js_handler</literal> is executed on worker process 0.
The optional <literal>worker_affinity</literal> 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 <literal>all</literal> mask allows the handler to be executed
in all worker processes.
</para>
<para>
Example:
<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://nginx.org/en/docs/njs/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}
</example>
</para>
</directive>
<directive name="js_preload_object">
<syntax><value>name.json</value> |
<value>name</value> from <value>file.json</value></syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.7.8</appeared-in>
<para>
Preloads an
<link doc="../njs/preload_objects.xml">immutable object</link>
at configure time.
The <literal>name</literal> is used as a name of the global variable
though which the object is available in njs code.
If the <literal>name</literal> is not specified,
the file name will be used instead.
<example>
js_preload_object map.json;
</example>
Here, the <literal>map</literal> is used as a name
while accessing the preloaded object.
</para>
<para>
Several <literal>js_preload_object</literal> directives can be specified.
</para>
</directive>
<directive name="js_set">
<syntax>
<value>$variable</value>
<value>module.function</value>
[<literal>nocache</literal>]</syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<para>
Sets an njs <literal>function</literal>
for the specified <literal>variable</literal>.
Since <link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>,
a module function can be referenced.
</para>
<para>
The function is called when
the variable is referenced for the first time for a given request.
The exact moment depends on a
<link doc="../dev/development_guide.xml" id="http_phases">phase</link>
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
<link doc="ngx_http_log_module.xml" id="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.
</para>
<para>
Since <link doc="../njs/changes.xml" id="njs0.8.6">0.8.6</link>,
if an optional argument <literal>nocache</literal> is specified,
the handler is called every time it is referenced.
Due to current limitations
of the <link doc="ngx_http_rewrite_module.xml">rewrite</link> module,
when a <literal>nocache</literal> variable is referenced by the
<link doc="ngx_http_rewrite_module.xml" id="set">set</link> directive
its handler should always return a fixed-length value.
</para>
<para>
<note>
As the <literal>js_set</literal> handler
returns its result immediately, it supports
only synchronous operations.
Thus, asynchronous operations such as
<link doc="../njs/reference.xml" id="r_subrequest">r.subrequest()</link>
or
<link doc="../njs/reference.xml" id="settimeout">setTimeout()</link>
are not supported.
</note>
</para>
<para>
<note>
The directive can be specified on the
<literal>server</literal> and <literal>location</literal> level
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
<directive name="js_shared_dict_zone">
<syntax>
<literal>zone</literal>=<value>name</value>:<value>size</value>
[<literal>timeout</literal>=<value>time</value>]
[<literal>type</literal>=<literal>string</literal>|<literal>number</literal>]
[<literal>evict</literal>]
[<literal>state</literal>=<value>file</value>]</syntax>
<default/>
<context>http</context>
<appeared-in>0.8.0</appeared-in>
<para>
Sets the <value>name</value> and <value>size</value> of the shared memory zone
that keeps the
key-value <link doc="../njs/reference.xml" id="dict">dictionary</link>
shared between worker processes.
</para>
<para>
By default the shared dictionary uses a string as a key and a value.
The optional <literal>type</literal> parameter
allows redefining the value type to number.
</para>
<para>
The optional <literal>timeout</literal> parameter sets
the time in milliseconds
after which all shared dictionary entries are removed from the zone.
If some entries require a different removal time, it can be set
with the <literal>timeout</literal> argument of the
<link doc="../njs/reference.xml" id="dict_add">add</link>,
<link doc="../njs/reference.xml" id="dict_incr">incr</link>, and
<link doc="../njs/reference.xml" id="dict_set">set</link>
methods
(<link doc="../njs/changes.xml" id="njs0.8.5">0.8.5</link>).
</para>
<para>
The optional <literal>evict</literal> parameter removes the oldest
key-value pair when the zone storage is exhausted.
</para>
<para>
The optional <literal>state</literal> parameter specifies a <value>file</value>
that keeps the shared dictionary state
in JSON format and makes it persistent across nginx restarts
(<link doc="../njs/changes.xml" id="njs0.9.1">0.9.1</link>).
</para>
<para>
Example:
<example>
example.conf:
# Creates a 1Mb dictionary with string values,
# removes key-value pairs after 60 seconds of inactivity:
js_shared_dict_zone zone=foo:1M timeout=60s;
# Creates a 512Kb dictionary with string values,
# forcibly removes oldest key-value pairs when the zone is exhausted:
js_shared_dict_zone zone=bar:512K timeout=30s evict;
# Creates a 32Kb permanent dictionary with number values:
js_shared_dict_zone zone=num:32k type=number;
# Creates a 1Mb dictionary with string values and persistent state:
js_shared_dict_zone zone=persistent:1M state=/tmp/dict.json;
example.js:
function get(r) {
r.return(200, ngx.shared.foo.get(r.args.key));
}
function set(r) {
r.return(200, ngx.shared.foo.set(r.args.key, r.args.value));
}
function del(r) {
r.return(200, ngx.shared.bar.delete(r.args.key));
}
function increment(r) {
r.return(200, ngx.shared.num.incr(r.args.key, 2));
}
</example>
</para>
</directive>
<directive name="js_var">
<syntax><value>$variable</value> [<value>value</value>]</syntax>
<default/>
<context>http</context>
<context>server</context>
<context>location</context>
<appeared-in>0.5.3</appeared-in>
<para>
Declares
a <link doc="../njs/reference.xml" id="r_variables">writable</link>
variable.
The value can contain text, variables, and their combination.
The variable is not overwritten after a redirect
unlike variables created with the
<link doc="ngx_http_rewrite_module.xml" id="set"/> directive.
</para>
<para>
<note>
The directive can be specified on the
<literal>server</literal> and <literal>location</literal> level
since <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>
</directive>
</section>
<section id="arguments" name="Request Argument">
<para>
Each HTTP njs handler receives one argument, a request
<link doc="../njs/reference.xml" id="http">object</link>.
</para>
</section>
</module>