Mercurial > hg > nginx-site
changeset 2245:87a0e2c73a25
Refactored njs documentation.
author | Yaroslav Zhuravlev <yar@nginx.com> |
---|---|
date | Mon, 24 Sep 2018 19:10:29 +0300 |
parents | 467aef18bf12 |
children | 32ba43abf9cd |
files | xml/en/GNUmakefile xml/en/docs/http/ngx_http_js_module.xml xml/en/docs/njs/cli.xml xml/en/docs/njs/compatibility.xml xml/en/docs/njs/examples.xml xml/en/docs/njs/index.xml xml/en/docs/njs/install.xml xml/en/docs/njs/njs_api.xml xml/en/docs/stream/ngx_stream_js_module.xml xml/index.xml xml/ru/GNUmakefile xml/ru/docs/http/ngx_http_js_module.xml xml/ru/docs/njs/cli.xml xml/ru/docs/njs/compatibility.xml xml/ru/docs/njs/examples.xml xml/ru/docs/njs/index.xml xml/ru/docs/stream/ngx_stream_js_module.xml |
diffstat | 17 files changed, 1727 insertions(+), 993 deletions(-) [+] |
line wrap: on
line diff
--- a/xml/en/GNUmakefile +++ b/xml/en/GNUmakefile @@ -125,6 +125,10 @@ REFS = \ njs/index \ njs/njs_changes \ njs/njs_api \ + njs/cli \ + njs/compatibility \ + njs/examples \ + njs/install \ TOP = \ download \
--- a/xml/en/docs/http/ngx_http_js_module.xml +++ b/xml/en/docs/http/ngx_http_js_module.xml @@ -9,21 +9,21 @@ <module name="Module ngx_http_js_module" link="/en/docs/http/ngx_http_js_module.html" lang="en" - rev="16"> + rev="17"> <section id="summary"> <para> The <literal>ngx_http_js_module</literal> module is used to implement location and variable handlers -in <link doc="../njs/">njs</link> — +in <link doc="../njs/index.xml">njs</link> — a subset of the JavaScript language. </para> <para> This module is not built by default. Download and install instructions are available -<link doc="../njs/index.xml" id="install">here</link>. +<link doc="../njs/install.xml">here</link>. </para> </section>
new file mode 100644 --- /dev/null +++ b/xml/en/docs/njs/cli.xml @@ -0,0 +1,47 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Command-line interface" + link="/en/docs/njs/cli.html" + lang="en" + rev="1"> + +<section> +<para> +njs scripts development and debugging can be performed +from the command-line. +The command-line utility is available after the installation of +the Linux <link doc="install.xml" id="install_package">package</link> +or after building from the +<link doc="install.xml" id="install_sources">sources</link>. +Compared to njs running inside nginx, +nginx objects +(<link doc="njs_api.xml" id="http">HTTP</link> and +<link doc="njs_api.xml" id="stream">Stream</link>) +are not available in the utility. +<example> +$ echo "2**3" | njs - +8 + +$ njs +>> var o = {a:[]} +undefined + +>> JSON.stringify(o, undefined,1) +{ + "a": [ + + ] +} +>> +</example> +</para> + +</section> + +</article>
new file mode 100644 --- /dev/null +++ b/xml/en/docs/njs/compatibility.xml @@ -0,0 +1,242 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Compatibility" + link="/en/docs/njs/compatibility.html" + lang="en" + rev="1"> + +<section> + +<para> +njs is created in compliance with +<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link> +(strict mode) with some +<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link> +and later extensions. +The compliance is still evolving. +</para> + +</section> + + +<section id="supported" name="What is currently supported"> + +<para> +<list type="bullet"> + +<listitem> +Boolean values, numbers, strings, objects, arrays, +functions, and regular expressions +</listitem> + +<listitem> +ES5.1 operators, ES7 exponentiation operators +</listitem> + +<listitem> +ES5.1 statements: <literal>var</literal>, <literal>if</literal>, +<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>, +<literal>for in</literal>, <literal>while</literal>, +<literal>do while</literal>, <literal>break</literal>, +<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>, +<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal> +</listitem> + +<listitem> +ES6 <literal>Number</literal> and +<literal>Math</literal> properties and methods +</listitem> + +<listitem> +<literal>String</literal> methods: +<list type="bullet"> + +<listitem> +ES5.1: +<literal>fromCharCode</literal>, <literal>concat</literal>, +<literal>slice</literal>, <literal>substring</literal>, +<literal>substr</literal>, <literal>charAt</literal>, +<literal>charCodeAt</literal>, <literal>indexOf</literal>, +<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>, +<literal>toUpperCase</literal>, <literal>trim</literal>, +<literal>search</literal>, <literal>match</literal>, <literal>split</literal>, +<literal>replace</literal> +</listitem> + +<listitem> +ES6: +<literal>fromCodePoint</literal>, <literal>codePointAt</literal>, +<literal>includes</literal>, <literal>startsWith</literal>, +<literal>endsWith</literal>, <literal>repeat</literal> +</listitem> + +<listitem> +non-standard: +<literal>bytesFrom</literal> (0.2.3) +<literal>fromUTF8</literal>, <literal>toUTF8</literal>, +<literal>fromBytes</literal>, <literal>toBytes</literal> +</listitem> +</list> + +</listitem> + +<listitem> +<literal>Object</literal> methods: +<list type="bullet"> +<listitem> +ES5.1: +<literal>create</literal> (support without properties list), +<literal>keys</literal>, +<literal>defineProperty</literal>, +<literal>defineProperties</literal>, +<literal>getOwnPropertyDescriptor</literal>, +<literal>getPrototypeOf</literal>, +<literal>hasOwnProperty</literal>, +<literal>isPrototypeOf</literal>, +<literal>preventExtensions</literal>, +<literal>isExtensible</literal>, +<literal>freeze</literal>, +<literal>isFrozen</literal>, +<literal>seal</literal>, +<literal>isSealed</literal> +</listitem> +</list> + +</listitem> + +<listitem> +<literal>Array</literal> methods: +<list type="bullet"> +<listitem> +ES5.1: +<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>, +<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>, +<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>, +<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>, +<literal>lastIndexOf</literal>, <literal>forEach</literal>, +<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>, +<literal>map</literal>, <literal>reduce</literal>, +<literal>reduceRight</literal> +</listitem> + +<listitem> +ES6: +<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>, +<literal>findIndex</literal> +</listitem> + +<listitem> +ES7: <literal>includes</literal> +</listitem> +</list> + +</listitem> + +<listitem> +ES5.1 <literal>Function</literal> methods: +<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal> +</listitem> + +<listitem> +ES5.1 <literal>RegExp</literal> methods: +<literal>test</literal>, <literal>exec</literal> +</listitem> + +<listitem> +ES5.1 <literal>Date</literal> methods +</listitem> + +<listitem> +ES5.1 <literal>JSON</literal> object +</listitem> + +<listitem> +ES5.1 global functions: +<literal>isFinite</literal>, <literal>isNaN</literal>, +<literal>parseFloat</literal>, <literal>parseInt</literal>, +<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>, +<literal>encodeURI</literal>, <literal>encodeURIComponent</literal> +</listitem> + +<listitem> +<literal>Error</literal> objects: +<literal>Error</literal>, <literal>EvalError</literal>, +<literal>InternalError</literal>, <literal>RangeError</literal>, +<literal>ReferenceError</literal>, <literal>SyntaxError</literal>, +<literal>TypeError</literal>, <literal>URIError</literal> +</listitem> + +<listitem> +<literal>setTimeout()</literal> and <literal>clearTimeout()</literal> functions +(0.2.0) +</listitem> + +<listitem> +<link url="https://nodejs.org/api/fs.html#fs_file_system">Node.js style</link> +<literal>File system</literal> methods: +<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>, +<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>, +<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal> +</listitem> + +<listitem> +<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">Node.js style</link> +<literal>Crypto</literal> methods (0.2.0): +<literal>crypto.createHash</literal>, +<literal>crypto.createHmac</literal> + +</listitem> + +</list> +</para> + +</section> + + +<section id="not_supported" name="What is not supported yet"> + +<para> +<list type="bullet"> + +<listitem> +ES6 <literal>let</literal> and <literal>const</literal> declarations +</listitem> + +<listitem> +labels +</listitem> + +<listitem> +<literal>arguments</literal> array +</listitem> + +<listitem> +<literal>eval</literal> function +</listitem> + +<listitem> +<literal>new Function()</literal> constructor +</listitem> + +<listitem> +<literal>setInterval</literal>, +<literal>setImmediate</literal> functions +</listitem> + +<listitem> +non-integer fractions (<literal>.235</literal>) +</listitem> + +</list> +</para> + +</section> + +</article> +
new file mode 100644 --- /dev/null +++ b/xml/en/docs/njs/examples.xml @@ -0,0 +1,438 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Examples" + link="/en/docs/njs/examples.html" + lang="en" + rev="1"> + +<section id="helloword" name="Hello World"> + +<para> +<path>nginx.conf</path>: +<example> +load_module modules/ngx_http_js_module.so; + +events {} + +http { + js_include hello_world.js; + + server { + listen 8000; + + location / { + js_content hello; + } + } +} + +</example> +</para> + +<para> +<literal>hello_world.js</literal>: +<example> +function hello(r) { + r.return(200, “Hello world!”); +} +</example> +</para> + +</section> + + +<section id="urldecode" name="URL Decoding"> + +<para> +<path>nginx.conf</path>: +<example> +js_include urldecode.js; + +js_set $decoded_foo decoded_foo; +</example> +</para> + +<para> +<path>urldecode.js</path>: +<example> +function decoded_foo(r) { + return decodeURIComponent(r.args.foo); +} +</example> +</para> + +</section> + + +<section id="urlencode" name="URL Encoding"> + +<para> +<path>nginx.conf</path>: +<example> +js_include urlencode.js; + +js_set $encoded_foo encoded_foo; +... + +location / { + proxy_pass http://example.com?foo=$encoded_foo; +} +</example> +</para> + +<para> +<path>urlencode.js</path>: +<example> +function encoded_foo(r) { + return encodeURIComponent('foo & bar?'); +} +</example> +</para> + +</section> + + +<section id="redirect" name="Internal Redirect"> + +<para> +<path>nginx.conf</path>: +<example> +js_include redirect.js; + +location /redirect { + js_content redirect; +} + +location @named { + return 200 named; +} +</example> +</para> + +<para> +<path>redirect.js</path>: +<example> +function redirect(r) { + r.internalRedirect('@named'); +} +</example> +</para> + +</section> + + +<section id="fast_response" name="Returning Fastest Response from Proxy"> + +<para> +<path>nginx.conf</path>: +<example> +js_include fastresponse.js; + +location /start { + js_content content; +} + +location /foo { + proxy_pass http://backend1; +} + +location /bar { + proxy_pass http://backend2; +} +</example> +</para> + +<para> +<path>fastresponse.js</path>: +<example> +function content(r) { + var n = 0; + + function done(res) { + if (n++ == 0) { + r.return(res.status, res.responseBody); + } + } + + r.subrequest('/foo', r.variables.args, done); + r.subrequest('/bar', r.variables.args, done); +} +</example> +</para> + +</section> + + +<section id="jwt" name="Creating HS JWT"> + +<para> +<path>nginx.conf</path>: +<example> +js_include hs_jwt.js; + +js_set $jwt jwt; +</example> +</para> + +<para> +<path>hs_jwt.js</path>: +<example> +function create_hs256_jwt(claims, key, valid) { + var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid }; + + var s = JSON.stringify(header).toBytes().toString('base64url') + '.' + + JSON.stringify(claims).toBytes().toString('base64url'); + + var h = require('crypto').createHmac('sha256', key); + + return s + '.' + h.update(s).digest().toString('base64url'); +} + +function jwt(r) { + var claims = { + "iss" : "nginx", + "sub" : "alice", + "foo" : 123, + "bar" : "qq", + "zyx" : false + }; + + return create_hs256_jwt(claims, 'foo', 600); +} +</example> +</para> + +</section> + + +<section id="subrequest" name="Accessing API from a Subrequest"> + +<para> +<path>nginx.conf</path>: +<example> +js_include subrequest.js; + +keyval_zone zone=foo:10m; +... + +location /keyval { + js_content set_keyval; +} + +location /version { + js_content version; +} + +location /api { + api write=on; +} +</example> +</para> + +<para> +<path>subrequest.js</path>: +<example> +function set_keyval(r) { + r.subrequest('/api/3/http/keyvals/foo', + { method: 'POST', + body: JSON.stringify({ foo: 789, bar: "ss dd 00" })}, + + function(res) { + if (res.status >= 300) { + r.return(res.status, res.responseBody); + return; + } + r.return(500); + }); +} + +function version(r) { + r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) { + if (res.status != 200) { + r.return(res.status); + return; + } + + var json = JSON.parse(res.responseBody); + r.return(200, json.version); + }); +} +</example> +</para> + +</section> + + +<section id="secure_link" name="Creating secure_link Hash"> + +<para> +<path>nginx.conf</path>: +<example> +js_include hash.js; + +js_set $new_foo create_secure_link; +... + +location / { + secure_link $cookie_foo; + secure_link_md5 "$uri mykey"; + ... +} + +location @login { + add_header Set-Cookie "foo=$new_foo; Max-Age=60"; + return 302 /; +} +</example> +</para> + +<para> +<path>hash.js</path>: +<example> +function create_secure_link(r) { + return require('crypto').createHash('md5') + .update(r.uri).update(" mykey") + .digest('base64url'); +} +</example> +</para> + +</section> + + +<section id="legacy" name="Legacy Examples"> + +<section id="legacy_stream" name="Injecting HTTP header using stream proxy"> + +<para> +Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>, +stream configuration +<link doc="../stream/ngx_stream_js_module.xml" id="example">example</link> +has been changed. +For njs <link doc="../njs/njs_changes.xml" id="njs0.2.3">0.2.3</link> +and earlier, use this configuration example: +<example> +load_module modules/ngx_stream_js_module.so; +... + +stream { + js_include stream.js; + + js_set $foo foo; + js_set $bar bar; + + server { + listen 12345; + + js_preread qux; + return $foo; + } + + server { + listen 12346; + + js_access xyz; + proxy_pass 127.0.0.1:8000; + js_filter baz; + } +} + +http { + server { + listen 8000; + location / { + return 200 $http_foo\n; + } + } +} +</example> +</para> + +<para> +The <path>stream.js</path> file: +<example> +var req = ''; +var matched = 0; +var line = ''; + +function qux(s) { + var n = s.buffer.indexOf('\n'); + if (n == -1) { + return s.AGAIN; + } + + line = s.buffer.substr(0, n); +} + +function foo(s) { + return line; +} + +function bar(s) { + var v = s.variables; + s.log("hello from bar() handler!"); + return "foo-var" + v.remote_port + "; pid=" + v.pid; +} + +// The filter processes one buffer per call. +// The buffer is available in s.buffer both for +// reading and writing. Called for both directions. + +function baz(s) { + if (s.fromUpstream || matched) { + return; + } + + // Disable certain addresses. + + if (s.remoteAddress.match('^192.*')) { + return s.ERROR; + } + + // Read HTTP request line. + // Collect bytes in 'req' until request + // line is read. Clear current buffer to + // disable output. + + req = req + s.buffer; + s.buffer = ''; + + var n = req.search('\n'); + + if (n != -1) { + // Inject a new HTTP header. + var rest = req.substr(n + 1); + req = req.substr(0, n + 1); + + var addr = s.remoteAddress; + + s.log('req:' + req); + s.log('rest:' + rest); + + // Output the result and skip further + // processing. + + s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest; + matched = 1; + } +} + +function xyz(s) { + if (s.remoteAddress.match('^192.*')) { + return s.ABORT; + } +} +</example> +</para> + +</section> + +</section> + +</article>
--- a/xml/en/docs/njs/index.xml +++ b/xml/en/docs/njs/index.xml @@ -9,192 +9,52 @@ <article name="njs scripting language" link="/en/docs/njs/index.html" lang="en" - rev="23"> - -<section id="summary"> + rev="24" + toc="no"> -<para> -njs is a subset of the JavaScript language that allows -implementing location and variable handlers in -<link doc="../http/ngx_http_js_module.xml">http</link> and -<link doc="../stream/ngx_stream_js_module.xml">stream</link>. -njs is created in compliance with -<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link> -(strict mode) with some -<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link> -extensions. -The compliance is still evolving. -</para> - -</section> - - -<section id="supported" name="What is currently supported"> +<section id="links"> <para> <list type="bullet"> <listitem> -Boolean values, numbers, strings, objects, arrays, -functions, and regular expressions -</listitem> - -<listitem> -ES5.1 operators, ES7 exponentiation operators -</listitem> - -<listitem> -ES5.1 statements: <literal>var</literal>, <literal>if</literal>, -<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>, -<literal>for in</literal>, <literal>while</literal>, -<literal>do while</literal>, <literal>break</literal>, -<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>, -<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal> -</listitem> - -<listitem> -ES6 <literal>Number</literal> and -<literal>Math</literal> properties and methods -</listitem> - -<listitem> -<literal>String</literal> methods: -<list type="bullet"> - -<listitem> -ES5.1: -<literal>fromCharCode</literal>, <literal>concat</literal>, -<literal>slice</literal>, <literal>substring</literal>, -<literal>substr</literal>, <literal>charAt</literal>, -<literal>charCodeAt</literal>, <literal>indexOf</literal>, -<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>, -<literal>toUpperCase</literal>, <literal>trim</literal>, -<literal>search</literal>, <literal>match</literal>, <literal>split</literal>, -<literal>replace</literal> +<link doc="install.xml"/> </listitem> <listitem> -ES6: -<literal>fromCodePoint</literal>, <literal>codePointAt</literal>, -<literal>includes</literal>, <literal>startsWith</literal>, -<literal>endsWith</literal>, <literal>repeat</literal> -</listitem> - -<listitem> -non-standard: -<literal>bytesFrom</literal> (0.2.3) -<literal>fromUTF8</literal>, <literal>toUTF8</literal>, -<literal>fromBytes</literal>, <literal>toBytes</literal> -</listitem> -</list> - +<link doc="njs_changes.xml"/> </listitem> <listitem> -<literal>Object</literal> methods: -<list type="bullet"> +<link doc="njs_api.xml"/> +</listitem> + <listitem> -ES5.1: -<literal>create</literal> (support without properties list), -<literal>keys</literal>, -<literal>defineProperty</literal>, -<literal>defineProperties</literal>, -<literal>getOwnPropertyDescriptor</literal>, -<literal>getPrototypeOf</literal>, -<literal>hasOwnProperty</literal>, -<literal>isPrototypeOf</literal>, -<literal>preventExtensions</literal>, -<literal>isExtensible</literal>, -<literal>freeze</literal>, -<literal>isFrozen</literal>, -<literal>seal</literal>, -<literal>isSealed</literal> -</listitem> -</list> - +<link doc="examples.xml"/> </listitem> <listitem> -<literal>Array</literal> methods: -<list type="bullet"> -<listitem> -ES5.1: -<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>, -<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>, -<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>, -<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>, -<literal>lastIndexOf</literal>, <literal>forEach</literal>, -<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>, -<literal>map</literal>, <literal>reduce</literal>, -<literal>reduceRight</literal> -</listitem> - -<listitem> -ES6: -<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>, -<literal>findIndex</literal> -</listitem> - -<listitem> -ES7: <literal>includes</literal> -</listitem> -</list> - -</listitem> - -<listitem> -ES5.1 <literal>Function</literal> methods: -<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal> -</listitem> - -<listitem> -ES5.1 <literal>RegExp</literal> methods: -<literal>test</literal>, <literal>exec</literal> +<link doc="compatibility.xml"/> </listitem> <listitem> -ES5.1 <literal>Date</literal> methods -</listitem> - -<listitem> -ES5.1 <literal>JSON</literal> object +<link doc="cli.xml"/> </listitem> +</list> +</para> + +<para> +<list type="bullet"> + <listitem> -ES5.1 global functions: -<literal>isFinite</literal>, <literal>isNaN</literal>, -<literal>parseFloat</literal>, <literal>parseInt</literal>, -<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>, -<literal>encodeURI</literal>, <literal>encodeURIComponent</literal> +<link doc="../http/ngx_http_js_module.xml"> +ngx_http_js_module</link> </listitem> <listitem> -<literal>Error</literal> objects: -<literal>Error</literal>, <literal>EvalError</literal>, -<literal>InternalError</literal>, <literal>RangeError</literal>, -<literal>ReferenceError</literal>, <literal>SyntaxError</literal>, -<literal>TypeError</literal>, <literal>URIError</literal> -</listitem> - -<listitem> -<literal>setTimeout()</literal> and <literal>clearTimeout()</literal> functions -(0.2.0) -</listitem> - -<listitem> -<link url="https://nodejs.org/api/fs.html#fs_file_system">Node.js style</link> -<literal>File system</literal> methods: -<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>, -<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>, -<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal> -</listitem> - -<listitem> -<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">Node.js style</link> -<literal>Crypto</literal> methods (0.2.0): -<literal>crypto.createHash</literal>, -<literal>crypto.createHmac</literal> - +<link doc="../stream/ngx_stream_js_module.xml"> +ngx_stream_js_module</link> </listitem> </list> @@ -203,171 +63,107 @@ ES5.1 global functions: </section> -<section id="not_supported" name="What is not supported yet"> +<section id="summary"> + +<para> +njs is a subset of the JavaScript language that allows +extending nginx functionality. +njs is created in compliance with +<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link> +(strict mode) with some +<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link> +and later extensions. +The compliance is still <link doc="compatibility.xml">evolving</link>. +</para> + +</section> + + +<section id="usecases" name="Use cases"> <para> <list type="bullet"> <listitem> -ES6 <literal>let</literal> and <literal>const</literal> declarations -</listitem> - -<listitem> -labels -</listitem> - -<listitem> -<literal>arguments</literal> array +Complex access control and security checks in njs +before a request reaches an upstream server </listitem> <listitem> -<literal>eval</literal> function -</listitem> - -<listitem> -<literal>new Function()</literal> constructor +Manipulating response headers </listitem> <listitem> -<literal>setInterval</literal>, -<literal>setImmediate</literal> functions -</listitem> - -<listitem> -non-integer fractions (<literal>.235</literal>) +Writing flexible asynchronous content handlers and filters </listitem> </list> +See <link doc="examples.xml">examples</link> and +<link url="https://www.nginx.com/blog/tag/nginscript/">blog posts</link> +for more njs use cases. </para> </section> -<section id="changelog" name="Change Log"> +<section id="example" name="Basic HTTP Example"> <para> -The complete list of njs changes is available -<link doc="njs_changes.xml">here</link>. -</para> -</section> - - -<section id="njs_api" name="njs API Reference"> - -<para> -njs API reference is available -<link doc="njs_api.xml">here</link>. -</para> -</section> - - -<section id="install" name="Download and install"> - -<para> -njs is available in two modules: +To use njs in nginx: <list type="bullet"> <listitem> -<link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link> +<para> +<link doc="install.xml">install</link> njs scripting language +</para> +</listitem> + +<listitem id="hello_world"> +<para> +create an njs script file, for example, <path>hello_world.js</path>. +See <link doc="njs_api.xml">Reference</link> +for the list of njs properties and methods. +<example> +function hello(r) { + r.return(200, “Hello world!”); +} +</example> +</para> </listitem> <listitem> -<link doc="../stream/ngx_stream_js_module.xml">ngx_stream_js_module</link> -</listitem> -</list> -Both modules are not built by default, -they should be either compiled from the sources -or installed as a Linux package. -In addition, the Linux package provides -njs command-line <link id="cli">utility</link>. -</para> +<para> +in the <path>nginx.conf</path> file, enable +<link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link> module +and specify the +<link doc="../http/ngx_http_js_module.xml" id="js_include">js_include</link> +directive +with the <path>hello_world.js</path> script file: +<example> +load_module modules/ngx_http_js_module.so; +events {} -<section id="install_package" name="Installing as a Linux package"> -<para> -For Linux, njs modules -<link doc="../../linux_packages.xml" id="dynmodules">packages</link> can be used: -<list type="bullet"> +http { + js_include hello_world.js; + + server { + listen 8000; -<listitem> -<literal>nginx-module-njs</literal> — njs -<link doc="../ngx_core_module.xml" id="load_module">dynamic</link> modules -</listitem> + location / { + js_content hello; + } + } +} -<listitem> -<literal>nginx-module-njs-dbg</literal> — debug symbols for the -<literal>nginx-module-njs</literal> package +</example> +</para> </listitem> </list> -</para> - -</section> - - -<section id="install_sources" name="Building from the sources"> - -<para> -The <link url="http://hg.nginx.org/njs">repository</link> -with njs sources can be cloned with the following command: -(requires <link url="https://www.mercurial-scm.org">Mercurial</link> client): -<example> -hg clone http://hg.nginx.org/njs -</example> -Then the modules should be compiled using the -<literal>--add-module</literal> configuration parameter: -<example> -./configure --add-module=<value>path-to-njs</value>/nginx -</example> -The modules can also be built as -<link doc="../ngx_core_module.xml" id="load_module">dynamic</link>: -<example> -./configure --add-dynamic-module=<value>path-to-njs</value>/nginx -</example> -</para> - -<para> -To build only njs command-line <link id="cli">utility</link>, run -<literal>./configure</literal> and <literal>make njs</literal> commands -from njs root directory. -The utility is available as <literal>./build/njs</literal>. -</para> - -</section> - -</section> - - -<section id="cli" name="Command-line interface"> - -<para> -njs scripts development and debugging can be performed -from the command-line. -The command-line utility is available after the installation of -the Linux <link id="install_package">package</link> -or after building from the <link id="install_sources">sources</link>. -Compared to njs running inside nginx, -nginx objects -(<link doc="njs_api.xml" id="http">HTTP</link> and -<link doc="njs_api.xml" id="stream">Stream</link>) -are not available in the utility. -<example> -$ echo "2**3" | njs - -8 - -$ njs ->> var o = {a:[]} -undefined - ->> JSON.stringify(o, undefined,1) -{ - "a": [ - - ] -} ->> -</example> +There is also a standalone <link doc="cli.xml">command line</link> utility +that can be used independently of nginx for njs development and debugging. </para> </section>
new file mode 100644 --- /dev/null +++ b/xml/en/docs/njs/install.xml @@ -0,0 +1,67 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Download and install" + link="/en/docs/njs/install.html" + lang="en" + rev="1"> + +<section id="install_package" name="Installing as a Linux package"> + +<para> +For Linux, njs modules +<link doc="../../linux_packages.xml" id="dynmodules">packages</link> can be used: +<list type="bullet"> + +<listitem> +<literal>nginx-module-njs</literal> — njs +<link doc="../ngx_core_module.xml" id="load_module">dynamic</link> modules +</listitem> + +<listitem> +<literal>nginx-module-njs-dbg</literal> — debug symbols for the +<literal>nginx-module-njs</literal> package +</listitem> + +</list> +</para> + +</section> + + +<section id="install_sources" name="Building from the sources"> + +<para> +The <link url="http://hg.nginx.org/njs">repository</link> +with njs sources can be cloned with the following command: +(requires <link url="https://www.mercurial-scm.org">Mercurial</link> client): +<example> +hg clone http://hg.nginx.org/njs +</example> +Then the modules should be compiled using the +<literal>--add-module</literal> configuration parameter: +<example> +./configure --add-module=<value>path-to-njs</value>/nginx +</example> +The modules can also be built as +<link doc="../ngx_core_module.xml" id="load_module">dynamic</link>: +<example> +./configure --add-dynamic-module=<value>path-to-njs</value>/nginx +</example> +</para> + +<para> +To build only njs command-line <link doc="cli.xml">utility</link>, run +<literal>./configure</literal> and <literal>make njs</literal> commands +from njs root directory. +The utility is available as <literal>./build/njs</literal>. +</para> + +</section> + +</article>
--- a/xml/en/docs/njs/njs_api.xml +++ b/xml/en/docs/njs/njs_api.xml @@ -9,7 +9,7 @@ <article name="njs API" link="/en/docs/njs/njs_api.html" lang="en" - rev="7"> + rev="8"> <section id="summary"> @@ -1278,391 +1278,4 @@ the <link id="s_allow">s.allow()</link> </section> -<section id="example" name="Examples"> - - -<section id="example_urldecode" name="URL Decoding"> - -<para> -<example> -js_include urldecode.js; - -js_set $decoded_foo decoded_foo; -</example> -</para> - -<para> -The <path>urldecode.js</path> file: -<example> -function decoded_foo(r) { - return decodeURIComponent(r.args.foo); -} -</example> -</para> - -</section> - - -<section id="example_urlencode" name="URL Encoding"> - -<para> -<example> -js_include urlencode.js; - -js_set $encoded_foo encoded_foo; -... - -location / { - proxy_pass http://example.com?foo=$encoded_foo; -} -</example> -</para> - -<para> -The <path>urlencode.js</path> file: -<example> -function encoded_foo(r) { - return encodeURIComponent('foo & bar?'); -} -</example> -</para> - -</section> - - -<section id="example_internal_redirect" name="Internal Redirect"> - -<para> -<example> -js_include redirect.js; - -location /redirect { - js_content redirect; -} - -location @named { - return 200 named; -} -</example> -</para> - -<para> -The <path>redirect.js</path> file: -<example> -function redirect(r) { - r.internalRedirect('@named'); -} -</example> -</para> - -</section> - - -<section id="example_fast_response" name="Returning Fastest Response from Proxy"> - -<para> -<example> -js_include fastresponse.js; - -location /start { - js_content content; -} - -location /foo { - proxy_pass http://backend1; -} - -location /bar { - proxy_pass http://backend2; -} -</example> -</para> - -<para> -The <path>fastresponse.js</path> file: -<example> -function content(r) { - var n = 0; - - function done(res) { - if (n++ == 0) { - r.return(res.status, res.responseBody); - } - } - - r.subrequest('/foo', r.variables.args, done); - r.subrequest('/bar', r.variables.args, done); -} -</example> -</para> - -</section> - - -<section id="example_jwt" name="Creating HS JWT"> - -<para> -<example> -js_include hs_jwt.js; - -js_set $jwt jwt; -</example> -</para> - -<para> -The <path>hs_jwt.js</path> file: -<example> -function create_hs256_jwt(claims, key, valid) { - var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid }; - - var s = JSON.stringify(header).toBytes().toString('base64url') + '.' - + JSON.stringify(claims).toBytes().toString('base64url'); - - var h = require('crypto').createHmac('sha256', key); - - return s + '.' + h.update(s).digest().toString('base64url'); -} - -function jwt(r) { - var claims = { - "iss" : "nginx", - "sub" : "alice", - "foo" : 123, - "bar" : "qq", - "zyx" : false - }; - - return create_hs256_jwt(claims, 'foo', 600); -} -</example> -</para> - -</section> - - -<section id="example_subrequest" name="Accessing API from a Subrequest"> - -<para> -<example> -js_include subrequest.js; - -keyval_zone zone=foo:10m; -... - -location /keyval { - js_content set_keyval; -} - -location /version { - js_content version; -} - -location /api { - api write=on; -} -</example> -</para> - -<para> -The <path>subrequest.js</path> file: -<example> -function set_keyval(r) { - r.subrequest('/api/3/http/keyvals/foo', - { method: 'POST', - body: JSON.stringify({ foo: 789, bar: "ss dd 00" })}, - - function(res) { - if (res.status >= 300) { - r.return(res.status, res.responseBody); - return; - } - r.return(500); - }); -} - -function version(r) { - r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) { - if (res.status != 200) { - r.return(res.status); - return; - } - - var json = JSON.parse(res.responseBody); - r.return(200, json.version); - }); -} -</example> -</para> - -</section> - - -<section id="example_secure_link" name="Creating secure_link Hash"> - -<para> -<example> -js_include hash.js; - -js_set $new_foo create_secure_link; -... - -location / { - secure_link $cookie_foo; - secure_link_md5 "$uri mykey"; - ... -} - -location @login { - add_header Set-Cookie "foo=$new_foo; Max-Age=60"; - return 302 /; -} -</example> -</para> - -<para> -The <path>hash.js</path> file: -<example> -function create_secure_link(r) { - return require('crypto').createHash('md5') - .update(r.uri).update(" mykey") - .digest('base64url'); -} -</example> -</para> - -</section> - - -<section id="example_legacy" name="Legacy Examples"> - - -<section id="example_legacy_stream" name="Stream Example"> - -<para> -Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>, -stream configuration -<link doc="../stream/ngx_stream_js_module.xml" id="example">example</link> -has been changed. -For njs <link doc="../njs/njs_changes.xml" id="njs-0.2.3">0.2.3</link> -and earlier, use this configuration example: -<example> -load_module modules/ngx_stream_js_module.so; -... - -stream { - js_include stream.js; - - js_set $foo foo; - js_set $bar bar; - - server { - listen 12345; - - js_preread qux; - return $foo; - } - - server { - listen 12346; - - js_access xyz; - proxy_pass 127.0.0.1:8000; - js_filter baz; - } -} - -http { - server { - listen 8000; - location / { - return 200 $http_foo\n; - } - } -} -</example> -</para> - -<para> -The <path>stream.js</path> file: -<example> -var req = ''; -var matched = 0; -var line = ''; - -function qux(s) { - var n = s.buffer.indexOf('\n'); - if (n == -1) { - return s.AGAIN; - } - - line = s.buffer.substr(0, n); -} - -function foo(s) { - return line; -} - -function bar(s) { - var v = s.variables; - s.log("hello from bar() handler!"); - return "foo-var" + v.remote_port + "; pid=" + v.pid; -} - -// The filter processes one buffer per call. -// The buffer is available in s.buffer both for -// reading and writing. Called for both directions. - -function baz(s) { - if (s.fromUpstream || matched) { - return; - } - - // Disable certain addresses. - - if (s.remoteAddress.match('^192.*')) { - return s.ERROR; - } - - // Read HTTP request line. - // Collect bytes in 'req' until request - // line is read. Clear current buffer to - // disable output. - - req = req + s.buffer; - s.buffer = ''; - - var n = req.search('\n'); - - if (n != -1) { - // Inject a new HTTP header. - var rest = req.substr(n + 1); - req = req.substr(0, n + 1); - - var addr = s.remoteAddress; - - s.log('req:' + req); - s.log('rest:' + rest); - - // Output the result and skip further - // processing. - - s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest; - matched = 1; - } -} - -function xyz(s) { - if (s.remoteAddress.match('^192.*')) { - return s.ABORT; - } -} -</example> -</para> - -</section> - -</section> - -</section> - </article>
--- a/xml/en/docs/stream/ngx_stream_js_module.xml +++ b/xml/en/docs/stream/ngx_stream_js_module.xml @@ -9,20 +9,20 @@ <module name="Module ngx_stream_js_module" link="/en/docs/stream/ngx_stream_js_module.html" lang="en" - rev="14"> + rev="15"> <section id="summary"> <para> The <literal>ngx_stream_js_module</literal> module is used to implement -handlers in <link doc="../njs/">njs</link> — +handlers in <link doc="../njs/index.xml">njs</link> — a subset of the JavaScript language. </para> <para> This module is not built by default. Download and install instructions are available -<link doc="../njs/index.xml" id="install">here</link>. +<link doc="../njs/install.xml">here</link>. </para> </section> @@ -36,7 +36,7 @@ This example is valid for njs <link doc="../njs/njs_changes.xml" id="njs-0.2.4">0.2.4</link>. For njs <link doc="../njs/njs_changes.xml" id="njs-0.2.3">0.2.3</link> and earlier, use -<link doc="../njs/njs_api.xml" id="example_legacy">this</link> example. +<link doc="../njs/examples.xml" id="legacy">this</link> example. </note> <example> load_module modules/ngx_stream_js_module.so;
--- a/xml/index.xml +++ b/xml/index.xml @@ -34,7 +34,7 @@ support and control API</link> for TLS c <event date="2018-09-18"> <para> -<link doc="en/docs/njs/">njs-0.2.4</link> +<link doc="en/docs/njs/index.xml">njs-0.2.4</link> version has been released, featuring <link doc="en/docs/njs/njs_api.xml" id="s_on">s.on()</link>, <link doc="en/docs/njs/njs_api.xml" id="s_off">s.off()</link>, @@ -56,7 +56,7 @@ mainline version has been released. <event date="2018-07-31"> <para> -<link doc="en/docs/njs/">njs-0.2.3</link> +<link doc="en/docs/njs/index.xml">njs-0.2.3</link> version has been released, featuring <link doc="en/docs/njs/njs_api.xml" id="string_bytesfrom">String.bytesFrom()</link>, <link doc="en/docs/njs/njs_api.xml" id="string_padstart">String.padStart()</link>, @@ -93,7 +93,7 @@ balancing method</link>. <event date="2018-06-19"> <para> -<link doc="en/docs/njs/">njs-0.2.2</link> +<link doc="en/docs/njs/index.xml">njs-0.2.2</link> version has been released, featuring HTTP <link doc="en/docs/njs/njs_api.xml" id="r_internal_redirect">internalRedirect()</link> method support @@ -119,7 +119,7 @@ mainline version has been released. <event date="2018-05-31"> <para> -<link doc="en/docs/njs/">njs-0.2.1</link> +<link doc="en/docs/njs/index.xml">njs-0.2.1</link> version has been <link doc="en/docs/njs/njs_changes.xml" id="njs0.2.1">released</link>. </para> @@ -178,7 +178,7 @@ mainline version has been released. <event date="2018-04-03"> <para> -<link doc="en/docs/njs/">njs-0.2.0</link> +<link doc="en/docs/njs/index.xml">njs-0.2.0</link> version has been released, featuring HTTP <link doc="en/docs/njs/njs_api.xml" id="subrequest">subrequest()</link> method support
--- a/xml/ru/GNUmakefile +++ b/xml/ru/GNUmakefile @@ -108,6 +108,10 @@ REFS = \ ngx_google_perftools_module \ njs/index \ njs/njs_api \ + njs/cli \ + njs/compatibility \ + njs/examples \ + njs/install \ TOP = \ download \
--- a/xml/ru/docs/http/ngx_http_js_module.xml +++ b/xml/ru/docs/http/ngx_http_js_module.xml @@ -9,21 +9,21 @@ <module name="Модуль ngx_http_js_module" link="/ru/docs/http/ngx_http_js_module.html" lang="ru" - rev="16"> + rev="17"> <section id="summary"> <para> Модуль <literal>ngx_http_js_module</literal> позволяет задавать обработчики location и переменных -на <link doc="../njs/">njs</link> — +на <link doc="../njs/index.xml">njs</link> — подмножестве языка JavaScript. </para> <para> По умолчанию этот модуль не собирается. Инструкция по сборке и установке доступны -<link doc="../njs/index.xml" id="install">здесь</link>. +<link doc="../njs/install.xml">здесь</link>. </para> </section>
new file mode 100644 --- /dev/null +++ b/xml/ru/docs/njs/cli.xml @@ -0,0 +1,46 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Интерфейс командной строки" + link="/ru/docs/njs/cli.html" + lang="ru" + rev="1"> + +<section> +<para> +Создание и отладка njs-скриптов может осуществляться +в командной строке. +Утилита командной строки доступна после установки +<link doc="install.xml" id="install_package">пакета</link> Linux +или после сборки из +<link doc="install.xml" id="install_sources">исходных файлов</link>. +В отличие от njs, запущенном внутри nginx, +в утилите недоступны объекты nginx +(<link doc="njs_api.xml" id="http">HTTP</link> и +<link doc="njs_api.xml" id="stream">Stream</link>). +<example> +$ echo "2**3" | njs - +8 + +$ njs +>> var o = {a:[]} +undefined + +>> JSON.stringify(o, undefined,1) +{ + "a": [ + + ] +} +>> +</example> +</para> + +</section> + +</article>
new file mode 100644 --- /dev/null +++ b/xml/ru/docs/njs/compatibility.xml @@ -0,0 +1,242 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Совместимость" + link="/ru/docs/njs/compatibility.html" + lang="ru" + rev="1"> + +<section> + +<para> +njs совместим с +<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link> +(строгий режим) c некоторыми расширениями +<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link> +и позже. +Совместимость находится в стадии развития. +</para> + +</section> + + +<section id="supported" name="Готовая функциональность"> + +<para> +<list type="bullet"> + +<listitem> +Логические значения, числа, строки, объекты, массивы, +функции и регулярные выражения +</listitem> + +<listitem> +ES5.1 операторы, ES7 операторы возведения в степень +</listitem> + +<listitem> +ES5.1 инструкции: <literal>var</literal>, <literal>if</literal>, +<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>, +<literal>for in</literal>, <literal>while</literal>, +<literal>do while</literal>, <literal>break</literal>, +<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>, +<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal> +</listitem> + +<listitem> +ES6 методы и свойства <literal>Number</literal> и +<literal>Math</literal> +</listitem> + +<listitem> +Методы <literal>String</literal>: +<list type="bullet"> + +<listitem> +ES5.1: +<literal>fromCharCode</literal>, <literal>concat</literal>, +<literal>slice</literal>, <literal>substring</literal>, +<literal>substr</literal>, <literal>charAt</literal>, +<literal>charCodeAt</literal>, <literal>indexOf</literal>, +<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>, +<literal>toUpperCase</literal>, <literal>trim</literal>, +<literal>search</literal>, <literal>match</literal>, <literal>split</literal>, +<literal>replace</literal> +</listitem> + +<listitem> +ES6: +<literal>fromCodePoint</literal>, <literal>codePointAt</literal>, +<literal>includes</literal>, <literal>startsWith</literal>, +<literal>endsWith</literal>, <literal>repeat</literal> +</listitem> + +<listitem> +нестандартные: +<literal>bytesFrom</literal> (0.2.3), +<literal>fromUTF8</literal>, <literal>toUTF8</literal>, +<literal>fromBytes</literal>, <literal>toBytes</literal> +</listitem> +</list> + +</listitem> + +<listitem> +Методы <literal>Object</literal>: +<list type="bullet"> +<listitem> +ES5.1: +<literal>create</literal> (поддержка без списка свойств), +<literal>keys</literal>, +<literal>defineProperty</literal>, +<literal>defineProperties</literal>, +<literal>getOwnPropertyDescriptor</literal>, +<literal>getPrototypeOf</literal>, +<literal>hasOwnProperty</literal>, +<literal>isPrototypeOf</literal>, +<literal>preventExtensions</literal>, +<literal>isExtensible</literal>, +<literal>freeze</literal>, +<literal>isFrozen</literal>, +<literal>seal</literal>, +<literal>isSealed</literal> +</listitem> +</list> + +</listitem> + +<listitem> +Методы <literal>Array</literal>: +<list type="bullet"> +<listitem> +ES5.1: +<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>, +<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>, +<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>, +<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>, +<literal>lastIndexOf</literal>, <literal>forEach</literal>, +<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>, +<literal>map</literal>, <literal>reduce</literal>, +<literal>reduceRight</literal> +</listitem> + +<listitem> +ES6: +<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>, +<literal>findIndex</literal> +</listitem> + +<listitem> +ES7: <literal>includes</literal> +</listitem> +</list> + +</listitem> + +<listitem> +ES5.1 методы <literal>Function</literal>: +<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal> +</listitem> + +<listitem> +ES5.1 методы <literal>RegExp</literal>: +<literal>test</literal>, <literal>exec</literal> +</listitem> + +<listitem> +ES5.1 методы <literal>Date</literal> +</listitem> + +<listitem> +ES5.1 объект <literal>JSON</literal> +</listitem> + +<listitem> +ES5.1 глобальные функции: +<literal>isFinite</literal>, <literal>isNaN</literal>, +<literal>parseFloat</literal>, <literal>parseInt</literal>, +<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>, +<literal>encodeURI</literal>, <literal>encodeURIComponent</literal> +</listitem> + +<listitem> +Объекты <literal>Error</literal>: +<literal>Error</literal>, <literal>EvalError</literal>, +<literal>InternalError</literal>, <literal>RangeError</literal>, +<literal>ReferenceError</literal>, <literal>SyntaxError</literal>, +<literal>TypeError</literal>, <literal>URIError</literal> +</listitem> + +<listitem> +Функции <literal>setTimeout()</literal> и <literal>clearTimeout()</literal> +(0.2.0) +</listitem> + +<listitem> +Методы <literal>File system</literal> +<link url="https://nodejs.org/api/fs.html#fs_file_system">стиль Node.js</link>: +<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>, +<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>, +<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal> +</listitem> + +<listitem> +Методы <literal>Crypto</literal> +<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">стиль Node.js</link> +(0.2.0): +<literal>crypto.createHash</literal>, +<literal>crypto.createHmac</literal> +</listitem> + +</list> +</para> + +</section> + + +<section id="not_supported" name="Функциональность в разработке"> + +<para> +<list type="bullet"> + +<listitem> +ES6 объявления <literal>let</literal> и <literal>const</literal> +</listitem> + +<listitem> +labels +</listitem> + +<listitem> +массив <literal>arguments</literal> +</listitem> + +<listitem> +функция <literal>eval</literal> +</listitem> + +<listitem> +конструктор <literal>new Function()</literal> +</listitem> + +<listitem> +функции <literal>setInterval</literal>, +<literal>setImmediate</literal> +</listitem> + +<listitem> +дроби без целой части (<literal>.235</literal>) +</listitem> + +</list> +</para> + +</section> + +</article> +
new file mode 100644 --- /dev/null +++ b/xml/ru/docs/njs/examples.xml @@ -0,0 +1,438 @@ +<?xml version="1.0"?> + +<!-- + Copyright (C) Nginx, Inc. + --> + +<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> + +<article name="Примеры использования" + link="/ru/docs/njs/examples.html" + lang="ru" + rev="1"> + +<section id="helloword" name="Hello World"> + +<para> +<path>nginx.conf</path>: +<example> +load_module modules/ngx_http_js_module.so; + +events {} + +http { + js_include hello_world.js; + + server { + listen 8000; + + location / { + js_content hello; + } + } +} + +</example> +</para> + +<para> +<literal>hello_world.js</literal>: +<example> +function hello(r) { + r.return(200, “Hello world!”); +} +</example> +</para> + +</section> + + +<section id="urldecode" name="Декодирование URL"> + +<para> +<path>nginx.conf</path>: +<example> +js_include urldecode.js; + +js_set $decoded_foo decoded_foo; +</example> +</para> + +<para> +<path>urldecode.js</path>: +<example> +function decoded_foo(r) { + return decodeURIComponent(r.args.foo); +} +</example> +</para> + +</section> + + +<section id="urlencode" name="Кодирование URL"> + +<para> +<path>nginx.conf</path>: +<example> +js_include urlencode.js; + +js_set $encoded_foo encoded_foo; +... + +location / { + proxy_pass http://example.com?foo=$encoded_foo; +} +</example> +</para> + +<para> +<path>urlencode.js</path>: +<example> +function encoded_foo(r) { + return encodeURIComponent('foo & bar?'); +} +</example> +</para> + +</section> + + +<section id="redirect" name="Внутренняя переадресация"> + +<para> +<path>nginx.conf</path>: +<example> +js_include redirect.js; + +location /redirect { + js_content redirect; +} + +location @named { + return 200 named; +} +</example> +</para> + +<para> +<path>redirect.js</path>: +<example> +function redirect(r) { + r.internalRedirect('@named'); +} +</example> +</para> + +</section> + + +<section id="fast_response" name="Возвращение самого быстрого ответа от прокси"> + +<para> +<path>nginx.conf</path>: +<example> +js_include fastresponse.js; + +location /start { + js_content content; +} + +location /foo { + proxy_pass http://backend1; +} + +location /bar { + proxy_pass http://backend2; +} +</example> +</para> + +<para> +<path>fastresponse.js</path>: +<example> +function content(r) { + var n = 0; + + function done(res) { + if (n++ == 0) { + r.return(res.status, res.responseBody); + } + } + + r.subrequest('/foo', r.variables.args, done); + r.subrequest('/bar', r.variables.args, done); +} +</example> +</para> + +</section> + + +<section id="jwt" name="Создание HS JWT"> + +<para> +<path>nginx.conf</path>: +<example> +js_include hs_jwt.js; + +js_set $jwt jwt; +</example> +</para> + +<para> +<path>hs_jwt.js</path>: +<example> +function create_hs256_jwt(claims, key, valid) { + var header = { "typ" : "JWT", "alg" : "HS256", "exp" : Date.now() + valid }; + + var s = JSON.stringify(header).toBytes().toString('base64url') + '.' + + JSON.stringify(claims).toBytes().toString('base64url'); + + var h = require('crypto').createHmac('sha256', key); + + return s + '.' + h.update(s).digest().toString('base64url'); +} + +function jwt(r) { + var claims = { + "iss" : "nginx", + "sub" : "alice", + "foo" : 123, + "bar" : "qq", + "zyx" : false + }; + + return create_hs256_jwt(claims, 'foo', 600); +} +</example> +</para> + +</section> + + +<section id="subrequest" name="Доступ к API из подзапроса"> + +<para> +<path>nginx.conf</path>: +<example> +js_include subrequest.js; + +keyval_zone zone=foo:10m; +... + +location /keyval { + js_content set_keyval; +} + +location /version { + js_content version; +} + +location /api { + api write=on; +} +</example> +</para> + +<para> +<path>subrequest.js</path>: +<example> +function set_keyval(r) { + r.subrequest('/api/3/http/keyvals/foo', + { method: 'POST', + body: JSON.stringify({ foo: 789, bar: "ss dd 00" })}, + + function(res) { + if (res.status >= 300) { + r.return(res.status, res.responseBody); + return; + } + r.return(500); + }); +} + +function version(r) { + r.subrequest('/api/3/nginx', { method: 'GET' }, function(res) { + if (res.status != 200) { + r.return(res.status); + return; + } + + var json = JSON.parse(res.responseBody); + r.return(200, json.version); + }); +} +</example> +</para> + +</section> + + +<section id="secure_link" name="Создание secure_link хэша"> + +<para> +<path>nginx.conf</path>: +<example> +js_include hash.js; + +js_set $new_foo create_secure_link; +... + +location / { + secure_link $cookie_foo; + secure_link_md5 "$uri mykey"; + ... +} + +location @login { + add_header Set-Cookie "foo=$new_foo; Max-Age=60"; + return 302 /; +} +</example> +</para> + +<para> +<path>hash.js</path>: +<example> +function create_secure_link(r) { + return require('crypto').createHash('md5') + .update(r.uri).update(" mykey") + .digest('base64url'); +} +</example> +</para> + +</section> + + +<section id="legacy" name="Устаревшие примеры"> + +<section id="legacy_stream" name="Внедрение HTTP-заголовка при помощи stream proxy"> + +<para> +Начиная с версии njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link> +<link doc="../stream/ngx_stream_js_module.xml" id="example">пример</link> +конфигурации в stream +был изменён. +Для njs <link doc="../njs/njs_changes.xml" id="njs0.2.3">0.2.3</link> +и более ранних версий необходимо использовать следующий пример конфигурации: +<example> +load_module modules/ngx_stream_js_module.so; +... + +stream { + js_include stream.js; + + js_set $foo foo; + js_set $bar bar; + + server { + listen 12345; + + js_preread qux; + return $foo; + } + + server { + listen 12346; + + js_access xyz; + proxy_pass 127.0.0.1:8000; + js_filter baz; + } +} + +http { + server { + listen 8000; + location / { + return 200 $http_foo\n; + } + } +} +</example> +</para> + +<para> +Файл <path>stream.js</path>: +<example> +var req = ''; +var matched = 0; +var line = ''; + +function qux(s) { + var n = s.buffer.indexOf('\n'); + if (n == -1) { + return s.AGAIN; + } + + line = s.buffer.substr(0, n); +} + +function foo(s) { + return line; +} + +function bar(s) { + var v = s.variables; + s.log("hello from bar() handler!"); + return "foo-var" + v.remote_port + "; pid=" + v.pid; +} + +// Фильтр обрабатывает один буфер за вызов. +// Буфер недоступен в s.buffer для +// чтения и записи. Вызывается в обоих направлениях. + +function baz(s) { + if (s.fromUpstream || matched) { + return; + } + + // Отключение определённых адресов. + + if (s.remoteAddress.match('^192.*')) { + return s.ERROR; + } + + // Чтение строки HTTP-запроса. + // Получение байт в 'req' до того как + // будет прочитана строка запроса. Очистка текущего буфера + // для отключения вывода. + + req = req + s.buffer; + s.buffer = ''; + + var n = req.search('\n'); + + if (n != -1) { + // Inject a new HTTP header. + var rest = req.substr(n + 1); + req = req.substr(0, n + 1); + + var addr = s.remoteAddress; + + s.log('req:' + req); + s.log('rest:' + rest); + + // Вывод результата и пропуск дальнейшей + // обработки. + + s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest; + matched = 1; + } +} + +function xyz(s) { + if (s.remoteAddress.match('^192.*')) { + return s.ABORT; + } +} +</example> +</para> + +</section> + +</section> + +</article>
--- a/xml/ru/docs/njs/index.xml +++ b/xml/ru/docs/njs/index.xml @@ -9,191 +9,52 @@ <article name="Сценарный язык njs" link="/ru/docs/njs/index.html" lang="ru" - rev="23"> - -<section id="summary"> + rev="24" + toc="no"> -<para> -njs - это подмножество языка JavaScript, который позволяет -задавать обработчики location и переменных в -<link doc="../http/ngx_http_js_module.xml">http</link> и -<link doc="../stream/ngx_stream_js_module.xml">stream</link>. -njs совместим с -<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link> -(строгий режим) c некоторыми расширениями -<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link>. -Совместимость находится в стадии развития. -</para> - -</section> - - -<section id="supported" name="Готовая функциональность"> +<section id="links"> <para> <list type="bullet"> <listitem> -Логические значения, числа, строки, объекты, массивы, -функции и регулярные выражения -</listitem> - -<listitem> -ES5.1 операторы, ES7 операторы возведения в степень -</listitem> - -<listitem> -ES5.1 инструкции: <literal>var</literal>, <literal>if</literal>, -<literal>else</literal>, <literal>switch</literal>, <literal>for</literal>, -<literal>for in</literal>, <literal>while</literal>, -<literal>do while</literal>, <literal>break</literal>, -<literal>continue</literal>, <literal>return</literal>, <literal>try</literal>, -<literal>catch</literal>, <literal>throw</literal>, <literal>finally</literal> -</listitem> - -<listitem> -ES6 методы и свойства <literal>Number</literal> и -<literal>Math</literal> -</listitem> - -<listitem> -Методы <literal>String</literal>: -<list type="bullet"> - -<listitem> -ES5.1: -<literal>fromCharCode</literal>, <literal>concat</literal>, -<literal>slice</literal>, <literal>substring</literal>, -<literal>substr</literal>, <literal>charAt</literal>, -<literal>charCodeAt</literal>, <literal>indexOf</literal>, -<literal>lastIndexOf</literal>, <literal>toLowerCase</literal>, -<literal>toUpperCase</literal>, <literal>trim</literal>, -<literal>search</literal>, <literal>match</literal>, <literal>split</literal>, -<literal>replace</literal> +<link doc="install.xml"/> </listitem> <listitem> -ES6: -<literal>fromCodePoint</literal>, <literal>codePointAt</literal>, -<literal>includes</literal>, <literal>startsWith</literal>, -<literal>endsWith</literal>, <literal>repeat</literal> -</listitem> - -<listitem> -нестандартные: -<literal>bytesFrom</literal> (0.2.3), -<literal>fromUTF8</literal>, <literal>toUTF8</literal>, -<literal>fromBytes</literal>, <literal>toBytes</literal> -</listitem> -</list> - +<link doc="njs_changes.xml">Изменения в njs</link> </listitem> <listitem> -Методы <literal>Object</literal>: -<list type="bullet"> +<link doc="njs_api.xml"/> +</listitem> + <listitem> -ES5.1: -<literal>create</literal> (поддержка без списка свойств), -<literal>keys</literal>, -<literal>defineProperty</literal>, -<literal>defineProperties</literal>, -<literal>getOwnPropertyDescriptor</literal>, -<literal>getPrototypeOf</literal>, -<literal>hasOwnProperty</literal>, -<literal>isPrototypeOf</literal>, -<literal>preventExtensions</literal>, -<literal>isExtensible</literal>, -<literal>freeze</literal>, -<literal>isFrozen</literal>, -<literal>seal</literal>, -<literal>isSealed</literal> -</listitem> -</list> - +<link doc="examples.xml"/> </listitem> <listitem> -Методы <literal>Array</literal>: -<list type="bullet"> -<listitem> -ES5.1: -<literal>isArray</literal>, <literal>slice</literal>, <literal>splice</literal>, -<literal>push</literal>, <literal>pop</literal>, <literal>unshift</literal>, -<literal>shift</literal>, <literal>reverse</literal>, <literal>sort</literal>, -<literal>join</literal>, <literal>concat</literal>, <literal>indexOf</literal>, -<literal>lastIndexOf</literal>, <literal>forEach</literal>, -<literal>some</literal>, <literal>every</literal>, <literal>filter</literal>, -<literal>map</literal>, <literal>reduce</literal>, -<literal>reduceRight</literal> -</listitem> - -<listitem> -ES6: -<literal>of</literal>, <literal>fill</literal>, <literal>find</literal>, -<literal>findIndex</literal> -</listitem> - -<listitem> -ES7: <literal>includes</literal> -</listitem> -</list> - -</listitem> - -<listitem> -ES5.1 методы <literal>Function</literal>: -<literal>call</literal>, <literal>apply</literal>, <literal>bind</literal> -</listitem> - -<listitem> -ES5.1 методы <literal>RegExp</literal>: -<literal>test</literal>, <literal>exec</literal> +<link doc="compatibility.xml"/> </listitem> <listitem> -ES5.1 методы <literal>Date</literal> -</listitem> - -<listitem> -ES5.1 объект <literal>JSON</literal> +<link doc="cli.xml"/> </listitem> +</list> +</para> + +<para> +<list type="bullet"> + <listitem> -ES5.1 глобальные функции: -<literal>isFinite</literal>, <literal>isNaN</literal>, -<literal>parseFloat</literal>, <literal>parseInt</literal>, -<literal>decodeURI</literal>, <literal>decodeURIComponent</literal>, -<literal>encodeURI</literal>, <literal>encodeURIComponent</literal> +<link doc="../http/ngx_http_js_module.xml"> +ngx_http_js_module</link> </listitem> <listitem> -Объекты <literal>Error</literal>: -<literal>Error</literal>, <literal>EvalError</literal>, -<literal>InternalError</literal>, <literal>RangeError</literal>, -<literal>ReferenceError</literal>, <literal>SyntaxError</literal>, -<literal>TypeError</literal>, <literal>URIError</literal> -</listitem> - -<listitem> -Функции <literal>setTimeout()</literal> и <literal>clearTimeout()</literal> -(0.2.0) -</listitem> - -<listitem> -Методы <literal>File system</literal> -<link url="https://nodejs.org/api/fs.html#fs_file_system">стиль Node.js</link>: -<literal>fs.readFile</literal>, <literal>fs.readFileSync</literal>, -<literal>fs.appendFile</literal>, <literal>fs.appendFileSync</literal>, -<literal>fs.writeFile</literal>, <literal>fs.writeFileSync</literal> -</listitem> - -<listitem> -Методы <literal>Crypto</literal> -<link url="https://nodejs.org/api/crypto.html#crypto_class_hash">стиль Node.js</link> -(0.2.0): -<literal>crypto.createHash</literal>, -<literal>crypto.createHmac</literal> +<link doc="../stream/ngx_stream_js_module.xml"> +ngx_stream_js_module</link> </listitem> </list> @@ -202,173 +63,109 @@ ES5.1 глобальные функции: </section> -<section id="not_supported" name="Функциональность в разработке"> +<section id="summary"> + +<para> +njs - это подмножество языка JavaScript, позволяющее +расширить функциональность nginx. +njs совместим с +<link url="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</link> +(строгий режим) c некоторыми расширениями +<link url="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</link> +и позже. +Совместимость находится в стадии +<link doc="compatibility.xml">развития</link>. +</para> + +</section> + + +<section id="usecases" name="Сценарии использования"> <para> <list type="bullet"> <listitem> -ES6 объявления <literal>let</literal> и <literal>const</literal> -</listitem> - -<listitem> -labels -</listitem> - -<listitem> -массив <literal>arguments</literal> +Комплексное управление доступом и проверка защиты при помощи njs +до получения запроса сервером группы </listitem> <listitem> -функция <literal>eval</literal> -</listitem> - -<listitem> -конструктор <literal>new Function()</literal> +Управление заголовками ответа </listitem> <listitem> -функции <literal>setInterval</literal>, -<literal>setImmediate</literal> -</listitem> - -<listitem> -дроби без целой части (<literal>.235</literal>) +Создание гибких асинхронных обработчиков содержимого и фильтров </listitem> </list> +Подробнее о сценариях использования +см. в <link doc="examples.xml">примерах</link> +и <link url="https://www.nginx.com/blog/tag/nginscript/">блогпостах</link>. </para> </section> -<section id="changelog" name="История изменений"> - -<para> -Полная история изменений njs доступна -<link doc="njs_changes.xml">здесь</link>. -</para> -</section> - -<section id="njs_api" name="Справочник njs API"> +<section id="example" name="Базовый пример HTTP"> <para> -Справочник njs API доступен -<link doc="njs_api.xml">здесь</link>. -</para> -</section> - - -<section id="install" name="Загрузка и установка"> - -<para> -njs доступен в двух модулях: +Чтобы использовать njs в nginx, необходимо: <list type="bullet"> <listitem> -<link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link> +<para> +<link doc="install.xml">установить</link> njs +</para> +</listitem> + +<listitem id="hello_world"> +<para> +создать файл сценария njs, например <path>hello_world.js</path>. +Описание свойств и методов языка njs +см. в <link doc="njs_api.xml">справочнике</link>. +<example> +function hello(r) { + r.return(200, “Hello world!”); +} +</example> +</para> </listitem> <listitem> -<link doc="../stream/ngx_stream_js_module.xml">ngx_stream_js_module</link> + +<para> +в файле <path>nginx.conf</path> включить +модуль <link doc="../http/ngx_http_js_module.xml">ngx_http_js_module</link> +и указать директиву +<link doc="../http/ngx_http_js_module.xml" id="js_include">js_include</link> +с файлом сценария <path>hello_world.js</path>: +<example> +load_module modules/ngx_http_js_module.so; + +events {} + +http { + js_include hello_world.js; + + server { + listen 8000; + + location / { + js_content hello; + } + } +} + +</example> +</para> </listitem> </list> -По умолчанию модули не собираются -их необходимо собрать из исходного кода -или установить из отдельного пакета Linux. -Кроме того, в пакете Linux предоставляется -<link id="cli">утилита</link> командной строки njs. -</para> - - -<section id="install_package" name="Установка пакета Linux"> -<para> -Для установки модулей njs на Linux могут быть использованы -<link doc="../../linux_packages.xml" id="dynmodules">пакеты</link>: -<list type="bullet"> - -<listitem> -<literal>nginx-module-njs</literal> — -<link doc="../ngx_core_module.xml" id="load_module">динамические</link> модули -njs -</listitem> - -<listitem> -<literal>nginx-module-njs-dbg</literal> — debug-символы для -пакета <literal>nginx-module-njs</literal> -</listitem> - -</list> + Также доступна отдельная утилита <link doc="cli.xml">командной строки</link>, +которая может использоваться независимо от nginx для разработки и отладки njs. </para> </section> - -<section id="install_sources" name="Установка из исходных файлов"> - -<para> -<link url="http://hg.nginx.org/njs">Репозиторий</link> -с исходным кодом njs можно клонировать следующей командой: -(необходим клиент <link url="https://www.mercurial-scm.org">Mercurial</link>): -<example> -hg clone http://hg.nginx.org/njs -</example> -Затем модули необходимо собрать с помощью -конфигурационного параметра <literal>--add-module</literal>: -<example> -./configure --add-module=<value>path-to-njs</value>/nginx -</example> -Модули также можно собрать как -<link doc="../ngx_core_module.xml" id="load_module">динамические</link>: -<example> -./configure --add-dynamic-module=<value>path-to-njs</value>/nginx -</example> -</para> - -<para> -Чтобы собрать только <link id="cli">утилиту</link> командной строки njs -необходимо запустить -команды <literal>./configure</literal> и <literal>make njs</literal> -из корневого каталога. -Утилита доступна как <literal>./build/njs</literal>. -</para> - -</section> - - -<section id="cli" name="Интерфейс командной строки"> - -<para> -Создание и отладка njs-скриптов может осуществляться -в командной строке. -Утилита командной строки доступна после установки -<link id="install_package">пакета</link> Linux -или после сборки из <link id="install_sources">исходных файлов</link>. -В отличие от njs, запущенном внутри nginx, -в утилите недоступны объекты nginx -(<link doc="njs_api.xml" id="http">HTTP</link> и -<link doc="njs_api.xml" id="stream">Stream</link>). -<example> -$ echo "2**3" | njs - -8 - -$ njs ->> var o = {a:[]} -undefined - ->> JSON.stringify(o, undefined,1) -{ - "a": [ - - ] -} ->> -</example> -</para> - -</section> - -</section> - </article>
--- a/xml/ru/docs/stream/ngx_stream_js_module.xml +++ b/xml/ru/docs/stream/ngx_stream_js_module.xml @@ -9,20 +9,20 @@ <module name="Модуль ngx_stream_js_module" link="/ru/docs/stream/ngx_stream_js_module.html" lang="ru" - rev="14"> + rev="15"> <section id="summary"> <para> Модуль <literal>ngx_stream_js_module</literal> позволяет задавать -обработчики на <link doc="../njs/">njs</link> — +обработчики на <link doc="../njs/index.xml">njs</link> — подмножестве языка JavaScript. </para> <para> По умолчанию этот модуль не собирается. Инструкция по сборке и установке доступны -<link doc="../njs/index.xml" id="install">здесь</link>. +<link doc="../njs/install.xml">здесь</link>. </para> </section> @@ -36,7 +36,7 @@ версией njs <link doc="../njs_changes.xml" id="njs-0.2.4">0.2.4</link>. Для версий njs <link doc="../njs_changes.xml" id="njs-0.2.3">0.2.3</link> и ранее необходимо использовать -<link doc="../njs_api.xml" id="example_legacy">этот</link> пример. +<link doc="../examples.xml" id="legacy">этот</link> пример. </note> <example> load_module modules/ngx_stream_js_module.so;