view xml/en/docs/http/ngx_http_js_module.xml @ 3039:e6b785b7e308

Minor fixes in njs documentation.
author Yaroslav Zhuravlev <yar@nginx.com>
date Tue, 06 Feb 2024 08:52:52 +0000
parents 58f0d9d7fe1d
children
line wrap: on
line source

<?xml version="1.0"?>

<!--
  Copyright (C) Nginx, Inc.
  -->

<!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="46">

<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 {
    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>function</value> | <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.
</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>
To stop filtering (following data chunks will be passed to client
without calling <literal>js_body_filter</literal>),
<link doc="../njs/reference.xml" id="r_done"><literal>r.done()</literal></link>
can be used.
</para>

<para>
If the filter function changes the length of the response body, then
it is required to clear out the <header>Content-Length</header> response header
(if any) in
<link id="js_header_filter"><literal>js_header_filter</literal></link>
to enforce chunked transfer encoding.
</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_content">
<syntax><value>function</value> | <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_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_header_filter">
<syntax><value>function</value> | <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>
<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_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>function</value> |
        <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>function</value> |
<value>module.function</value></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>
<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>]</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 after which all shared dictionary entries are removed from the zone.
</para>

<para>
The optional <literal>evict</literal> parameter removes the oldest
key-value pair when the zone storage is exhausted.
</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;

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>