changeset 2237:5268c13196f2

Documented njs changes triggered by njs-0.2.4.
author Yaroslav Zhuravlev <yar@nginx.com>
date Thu, 13 Sep 2018 21:10:42 +0300
parents 9f0f4f5c1a30
children 0761b770a94e
files xml/en/docs/njs/njs_api.xml xml/en/docs/njs/njs_changes.xml xml/en/docs/stream/ngx_stream_js_module.xml xml/index.xml xml/ru/docs/stream/ngx_stream_js_module.xml
diffstat 5 files changed, 610 insertions(+), 172 deletions(-) [+]
line wrap: on
line diff
--- a/xml/en/docs/njs/njs_api.xml	Mon Sep 17 06:59:29 2018 +0000
+++ b/xml/en/docs/njs/njs_api.xml	Thu Sep 13 21:10:42 2018 +0300
@@ -9,7 +9,7 @@
 <article name="njs API"
         link="/en/docs/njs/njs_api.html"
         lang="en"
-        rev="6">
+        rev="7">
 
 <section id="summary">
 
@@ -1004,7 +1004,6 @@
 <tag-desc>
 arguments string
 </tag-desc>
-
 <tag-name><literal>body</literal></tag-name>
 <tag-desc>
 request body
@@ -1038,58 +1037,48 @@
 <link doc="../stream/ngx_stream_js_module.xml">ngx_stream_js_module</link>
 module.
 All string properties of the object are <link id="string">byte strings</link>.
+</para>
 
+<para>
+<note>
+Prior to njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the stream session object had some properties which are currently
+<link id="stream_obsolete">removed</link>.
+</note>
+</para>
+
+<para>
 <list type="tag">
 
-<tag-name><literal>s.remoteAddress</literal></tag-name>
-<tag-desc>
-client address, read-only
-</tag-desc>
-
-<tag-name><literal>s.eof</literal></tag-name>
+<tag-name id="s_allow"><literal>s.allow()</literal></tag-name>
 <tag-desc>
-a boolean read-only property, true if the current buffer is the last buffer
-</tag-desc>
-
-<tag-name><literal>s.fromUpstream</literal></tag-name>
-<tag-desc>
-a boolean read-only property,
-true if the current buffer is from the upstream server to the client
-</tag-desc>
-
-<tag-name><literal>s.buffer</literal></tag-name>
-<tag-desc>
-the current buffer, writable
+successfully finalizes the phase handler
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>)
 </tag-desc>
 
-<tag-name><literal>s.variables{}</literal></tag-name>
+<tag-name id="s_decline"><literal>s.decline()</literal></tag-name>
 <tag-desc>
-nginx variables object, read-only
+finalizes the phase handler and passes control to the next handler
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>)
 </tag-desc>
 
-<tag-name><literal>s.OK</literal></tag-name>
+<tag-name id="s_deny"><literal>s.deny()</literal></tag-name>
 <tag-desc>
-the <literal>OK</literal> return code
+finalizes the phase handler with the access error code
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>)
 </tag-desc>
 
-<tag-name><literal>s.DECLINED</literal></tag-name>
+<tag-name id="s_done"><literal>s.done</literal>(<value>[code]</value>)</tag-name>
 <tag-desc>
-the <literal>DECLINED</literal> return code
+successfully finalizes the current phase handler
+or finalizes it with the specified numeric code
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>).
 </tag-desc>
 
-<tag-name><literal>s.AGAIN</literal></tag-name>
-<tag-desc>
-the <literal>AGAIN</literal> return code
-</tag-desc>
-
-<tag-name><literal>s.ERROR</literal></tag-name>
+<tag-name><literal>s.error(<value>string</value>)</literal></tag-name>
 <tag-desc>
-the <literal>ERROR</literal> return code
-</tag-desc>
-
-<tag-name><literal>s.ABORT</literal></tag-name>
-<tag-desc>
-the <literal>ABORT</literal> return code
+writes a sent <literal>string</literal> to the error log
+on the <literal>error</literal> level of logging
 </tag-desc>
 
 <tag-name><literal>s.log(<value>string</value>)</literal></tag-name>
@@ -1098,16 +1087,187 @@
 on the <literal>info</literal> level of logging
 </tag-desc>
 
+<tag-name id="s_off"><literal>s.off(<value>eventName</value>)</literal></tag-name>
+<tag-desc>
+unregisters the callback set by the <link id="s_on">s.on()</link> method
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>)
+</tag-desc>
+
+<tag-name id="s_on"><literal>s.on(<value>event</value>,
+<value>callback</value>)</literal></tag-name>
+<tag-desc>
+registers a <literal>callback</literal> for the specified <literal>event</literal>
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>).
+
+<para>
+An <literal>event</literal> may be one of the following strings:
+<list type="tag">
+<tag-name><literal>upload</literal></tag-name>
+<tag-desc>
+new data from a client
+</tag-desc>
+
+<tag-name><literal>download</literal></tag-name>
+<tag-desc>
+new data to a client
+</tag-desc>
+
+</list>
+</para>
+
+<para>
+The completion callback has the following prototype:
+<literal>callback(data, flags)</literal>, where
+<literal>data</literal> is string,
+<literal>flags</literal> is an object
+with the following properties:
+<list type="tag">
+<tag-name id="s_on_callback_last"><literal>last</literal></tag-name>
+<tag-desc>
+a boolean value, true if data is a last buffer.
+</tag-desc>
+
+</list>
+</para>
+</tag-desc>
+
+<tag-name><literal>s.remoteAddress</literal></tag-name>
+<tag-desc>
+client address, read-only
+</tag-desc>
+
+<tag-name id="s_send"><literal>s.send(<value>data</value>[,
+<value>options</value>])</literal></tag-name>
+<tag-desc>
+sends the data to the client
+(<link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>).
+The <literal>options</literal> is an object used
+to override nginx buffer flags derived from an incoming data chunk buffer.
+The flags can be overriden with the following flags:
+<para>
+<list type="tag">
+
+<tag-name><literal>last</literal></tag-name>
+<tag-desc>
+boolean, true if the buffer is the last buffer
+</tag-desc>
+
+<tag-name><literal>flush</literal></tag-name>
+<tag-desc>
+boolean, true if the buffer should have the <literal>flush</literal> flag
+</tag-desc>
+</list>
+</para>
+The method can be called multiple times per callback invocation.
+</tag-desc>
+
+<tag-name><literal>s.variables{}</literal></tag-name>
+<tag-desc>
+nginx variables object, read-only
+</tag-desc>
+
 <tag-name><literal>s.warn(<value>string</value>)</literal></tag-name>
 <tag-desc>
 writes a sent <literal>string</literal> to the error log
 on the <literal>warning</literal> level of logging
 </tag-desc>
 
-<tag-name><literal>s.error(<value>string</value>)</literal></tag-name>
+</list>
+</para>
+
+
+<section id="stream_obsolete" name="Obsolete properties">
+
+<para>
+These properties have been removed
+in njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>
+and are not backward compatible with the existing njs code.
+</para>
+
+<para>
+<list type="tag">
+
+<tag-name id="s_abort"><literal>s.ABORT</literal></tag-name>
+<tag-desc>
+the <literal>ABORT</literal> return code
+<note>
+Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the <link id="s_deny">s.deny()</link> method should be used instead.
+</note>
+</tag-desc>
+
+<tag-name><literal>s.AGAIN</literal></tag-name>
+<tag-desc>
+the <literal>AGAIN</literal> return code
+<note>
+Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the corresponding behavior is achieved if no
+<link id="s_allow">s.allow()</link>,
+<link id="s_deny">s.deny()</link>,
+<link id="s_decline">s.decline()</link>,
+<link id="s_done">s.done()</link>
+is invoked and a callback is registered.
+</note>
+</tag-desc>
+
+<tag-name id="s_buffer"><literal>s.buffer</literal></tag-name>
 <tag-desc>
-writes a sent <literal>string</literal> to the error log
-on the <literal>error</literal> level of logging
+the current buffer, writable
+<note>
+Starting from <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the <link id="s_send">s.send()</link> method should be used for writing.
+For reading, the current buffer is available as the first argument of the
+<literal>event</literal> callback.
+</note>
+</tag-desc>
+
+<tag-name><literal>s.DECLINED</literal></tag-name>
+<tag-desc>
+the <literal>DECLINED</literal> return code
+<note>
+Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the <link id="s_decline">s.decline()</link> method should be used instead.
+</note>
+</tag-desc>
+
+<tag-name><literal>s.eof</literal></tag-name>
+<tag-desc>
+a boolean read-only property, true if the current buffer is the last buffer
+<note>
+Starting from <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the <link id="s_on_callback_last">flags.last</link> property
+should be used instead.
+</note>
+</tag-desc>
+
+<tag-name><literal>s.ERROR</literal></tag-name>
+<tag-desc>
+the <literal>ERROR</literal> return code
+<note>
+Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+an appropriate exception can be thrown to report an error.
+</note>
+</tag-desc>
+
+<tag-name><literal>s.fromUpstream</literal></tag-name>
+<tag-desc>
+a boolean read-only property,
+true if the current buffer is from the upstream server to the client
+<note>
+Starting from <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+a corresponding <link id="s_on">event</link>
+(<literal>upload</literal> or <literal>download</literal>)
+should be used to handle data to or from client.
+</note>
+</tag-desc>
+
+<tag-name id="s_ok"><literal>s.OK</literal></tag-name>
+<tag-desc>
+the <literal>OK</literal> return code
+<note>
+Starting from njs <link doc="../njs/njs_changes.xml" id="njs0.2.4">0.2.4</link>,
+the <link id="s_allow">s.allow()</link> method should be used instead.
+</note>
 </tag-desc>
 
 </list>
@@ -1115,6 +1275,8 @@
 
 </section>
 
+</section>
+
 
 <section id="example" name="Examples">
 
@@ -1370,6 +1532,137 @@
 
 </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/njs/njs_changes.xml	Mon Sep 17 06:59:29 2018 +0000
+++ b/xml/en/docs/njs/njs_changes.xml	Thu Sep 13 21:10:42 2018 +0300
@@ -9,9 +9,182 @@
 <article name="njs Changes"
         link="/en/docs/njs/njs_changes.html"
         lang="en"
-        rev="6"
+        rev="7"
         toc="no">
 
+<section id="njs0.2.4" name="Changes with 0.2.4">
+
+<para>
+Release Date:
+18 September 2018
+</para>
+
+<para>
+nginx modules:
+<list type="bullet">
+
+<listitem>
+<para>
+Change:
+stream module handlers refactored.
+</para>
+
+<para>
+New methods and properties:
+<link doc="njs_api.xml" id="s_on">s.on()</link>,
+<link doc="njs_api.xml" id="s_off">s.off()</link>,
+<link doc="njs_api.xml" id="s_allow">s.allow()</link>,
+<link doc="njs_api.xml" id="s_done">s.done()</link>,
+<link doc="njs_api.xml" id="s_decline">s.decline()</link>,
+<link doc="njs_api.xml" id="s_deny">s.deny()</link>.
+</para>
+
+<para>
+Removed properties of the
+<link doc="njs_api.xml" id="stream">Stream</link> object:
+<literal>s.OK</literal>,
+<literal>s.ABORT</literal>,
+<literal>s.AGAIN</literal>,
+<literal>s.DECLINED</literal>,
+<literal>s.ERROR</literal>
+(replaced with
+<link doc="njs_api.xml" id="s_allow">s.allow()</link>,
+<link doc="njs_api.xml" id="s_done">s.done()</link>,
+<link doc="njs_api.xml" id="s_deny">s.deny()</link>).
+</para>
+
+<para>
+<literal>s.buffer</literal>
+(for reading replaced with data argument of
+the corresponding callback, for writing use
+<link doc="njs_api.xml" id="s_send">s.send()</link>).
+</para>
+
+<para>
+<literal>s.fromUpstream</literal>
+(replaced with a callback for a corresponding event).
+</para>
+
+<para>
+<literal>s.eof</literal>
+(replaced with <literal></literal>
+<link doc="njs_api.xml" id="s_on_callback_last">flags.last</link>).
+</para>
+
+</listitem>
+
+</list>
+</para>
+
+<para>
+Core:
+<list type="bullet">
+
+<listitem>
+<para>
+Feature:
+added <literal>Function.prototype.length</literal>.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Feature:
+introduced sandboxing mode.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Improvement:
+added exception strings where appropriate.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Improvement:
+improved wording for primitive type conversion exception.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+throwing <literal>TypeError</literal>
+for attempts to change frozen properties.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+fixed <literal>Object.defineProperty()</literal> for existing properties.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+respecting the enumerable attribute while iterating by for in.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+respecting writable attribute for property handlers.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+fixed exception handling in arguments of a function.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+fixed <literal>Object.prototype.toString</literal> for different value types.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+fixed <literal>Object()</literal> constructor for object types arguments.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+fixed comparison of objects and strings.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+fixed <literal>String.slice()</literal> for undefined arguments.
+</para>
+</listitem>
+
+<listitem>
+<para>
+Bugfix:
+miscellaneous additional bugs have been fixed.
+</para>
+</listitem>
+
+</list>
+</para>
+
+</section>
+
+
 <section id="njs0.2.3" name="Changes with 0.2.3">
 
 <para>
--- a/xml/en/docs/stream/ngx_stream_js_module.xml	Mon Sep 17 06:59:29 2018 +0000
+++ b/xml/en/docs/stream/ngx_stream_js_module.xml	Thu Sep 13 21:10:42 2018 +0300
@@ -9,7 +9,7 @@
 <module name="Module ngx_stream_js_module"
         link="/en/docs/stream/ngx_stream_js_module.html"
         lang="en"
-        rev="12">
+        rev="13">
 
 <section id="summary">
 
@@ -31,6 +31,13 @@
 <section id="example" name="Example Configuration">
 
 <para>
+<note>
+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.
+</note>
 <example>
 load_module modules/ngx_stream_js_module.so;
 ...
@@ -38,22 +45,22 @@
 stream {
     js_include stream.js;
 
-    js_set $foo foo;
     js_set $bar bar;
+    js_set $req_line req_line;
 
     server {
         listen 12345;
 
-        js_preread qux;
-        return     $foo;
+        js_preread preread;
+        return     $req_line;
     }
 
     server {
         listen 12346;
 
-        js_access  xyz;
+        js_access  access;
         proxy_pass 127.0.0.1:8000;
-        js_filter  baz;
+        js_filter  header_inject;
     }
 }
 
@@ -71,76 +78,55 @@
 <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;
+    return "bar-var" + v.remote_port + "; pid=" + v.pid;
+}
+
+function preread(s) {
+    s.on('upload', function (data, flags) {
+        var n = data.indexOf('\n');
+        if (n != -1) {
+            line = data.substr(0, n);
+            s.done();
+        }
+    });
+}
+
+function req_line(s) {
+    return line;
 }
 
-// The filter processes one buffer per call.
-// The buffer is available in s.buffer both for
-// reading and writing.  Called for both directions.
+// Read HTTP request line.
+// Collect bytes in 'req' until
+// request line is read.
+// Injects HTTP header into a client's request
 
-function baz(s) {
-    if (s.fromUpstream || matched) {
+var my_header =  'Foo: foo';
+function header_inject(s) {
+    var req = '';
+    s.on('upload', function(data, flags) {
+        req += data;
+        var n = req.search('\n');
+        if (n != -1) {
+            var rest = req.substr(n + 1);
+            req = req.substr(0, n + 1);
+            s.send(req + my_header + '\r\n' + rest, flags);
+            s.off('upload');
+        }
+    });
+}
+
+function access(s) {
+    if (s.remoteAddress.match('^192.*')) {
+        s.abort();
         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;
-    }
+    s.allow();
 }
 </example>
 </para>
--- a/xml/index.xml	Mon Sep 17 06:59:29 2018 +0000
+++ b/xml/index.xml	Thu Sep 13 21:10:42 2018 +0300
@@ -7,6 +7,21 @@
 
 <news name="nginx news" link="/" lang="en">
 
+<event date="2018-09-18">
+<para>
+<link doc="en/docs/njs_about.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>,
+<link doc="en/docs/njs/njs_api.xml" id="s_allow">s.allow()</link>,
+<link doc="en/docs/njs/njs_api.xml" id="s_done">s.done()</link>,
+<link doc="en/docs/njs/njs_api.xml" id="s_decline">s.decline()</link>,
+<link doc="en/docs/njs/njs_api.xml" id="s_deny">s.deny()</link>
+methods support
+and <link doc="en/docs/njs/njs_changes.xml" id="njs0.2.4">more</link>.
+</para>
+</event>
+
 <event date="2018-08-28">
 <para>
 <link doc="en/download.xml">nginx-1.15.3</link>
--- a/xml/ru/docs/stream/ngx_stream_js_module.xml	Mon Sep 17 06:59:29 2018 +0000
+++ b/xml/ru/docs/stream/ngx_stream_js_module.xml	Thu Sep 13 21:10:42 2018 +0300
@@ -9,7 +9,7 @@
 <module name="Модуль ngx_stream_js_module"
         link="/ru/docs/stream/ngx_stream_js_module.html"
         lang="ru"
-        rev="12">
+        rev="13">
 
 <section id="summary">
 
@@ -31,6 +31,13 @@
 <section id="example" name="Пример конфигурации">
 
 <para>
+<note>
+Данный пример необходимо использовать с
+версией 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> пример.
+</note>
 <example>
 load_module modules/ngx_stream_js_module.so;
 ...
@@ -38,22 +45,22 @@
 stream {
     js_include stream.js;
 
-    js_set $foo foo;
     js_set $bar bar;
+    js_set $req_line req_line;
 
     server {
         listen 12345;
 
-        js_preread qux;
-        return     $foo;
+        js_preread preread;
+        return     $req_line;
     }
 
     server {
         listen 12346;
 
-        js_access  xyz;
+        js_access  access;
         proxy_pass 127.0.0.1:8000;
-        js_filter  baz;
+        js_filter  header_inject;
     }
 }
 
@@ -71,76 +78,40 @@
 <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;
+    return "bar-var" + v.remote_port + "; pid=" + v.pid;
+}
+
+function preread(s) {
+    s.on('upload', function (data, flags) {
+        var n = data.indexOf('\n');
+        if (n != -1) {
+            line = data.substr(0, n);
+            s.done();
+        }
+    });
 }
 
-// Фильтр обрабатывает один буфер за вызов.
-// Буфер недоступен в s.buffer для
-// чтения и записи.  Вызывается в обоих направлениях.
+function req_line(s) {
+    return line;
+}
 
-function baz(s) {
-    if (s.fromUpstream || matched) {
+// Чтение строки HTTP-запроса.
+// Получение байт в 'req' до того как
+// будет прочитана строка запроса.
+// Добавление HTTP-заголовка в запрос клиента
+
+function access(s) {
+    if (s.remoteAddress.match('^192.*')) {
+        s.abort();
         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) {
-        // Вставка нового HTTP-заголовка.
-        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;
-    }
+    s.allow();
 }
 </example>
 </para>