view xml/en/docs/njs/examples.xml @ 3043:9eadb98ec770

Free nginx: removed commercial version documentation.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 14 Feb 2024 20:05:49 +0300
parents 24b379907b0f
children
line wrap: on
line source

<?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="22">

<section id="summary">

<para>
The examples work since
<link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>.
</para>

</section>


<section id="helloword" name="Hello World">

<para>
<path>nginx.conf</path>:
<example>
events {}

http {
    js_import http.js;

    server {
        listen 8000;

        location / {
            js_content http.hello;
        }
    }
}
</example>
</para>

<para>
<literal>http.js</literal>:
<example>
function hello(r) {
    r.return(200, "Hello world!");
}

export default {hello};
</example>
</para>

</section>


<section id="http_auth" name="HTTP Аuthorization">


<section id="jwt" name="Creating HS JWT">

<para>
<path>nginx.conf</path>:
<example>
js_import http.js;

js_set $jwt http.jwt;
</example>
</para>

<para>
<path>http.js</path>:
<example>
function generate_hs256_jwt(claims, key, valid) {
    var header = { typ: "JWT",  alg: "HS256" };
    var claims = Object.assign(claims, {exp: Math.floor(Date.now()/1000) + valid});

    var s = [header, claims].map(JSON.stringify)
                            .map(v=>v.toString('base64url'))
                            .join('.');

    var h = require('crypto').createHmac('sha256', key);

    return s + '.' + h.update(s).digest('base64url');
}

function jwt(r) {
    var claims = {
        iss: "nginx",
        sub: "alice",
        foo: 123,
        bar: "qq",
        zyx: false
    };

    return generate_hs256_jwt(claims, 'foo', 600);
}

export default {jwt};
</example>
</para>

</section>


<section id="secure_link" name="Creating secure_link Hash">

<para>
<path>nginx.conf</path>:
<example>
js_import http.js;

js_set $new_foo http.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>http.js</path>:
<example>
function create_secure_link(r) {
    return require('crypto').createHash('md5')
                            .update(r.uri).update(" mykey")
                            .digest('base64url');
}

export default {create_secure_link};
</example>
</para>

</section>


<section id="jwt_field" name="Getting Arbitrary Field from JWT
                              as nginx Variable">

<para>
In the following example, the <literal>sub</literal> field
is extracted from JWT payload.
The JWT token is taken from the <header>Authorization</header> header.
</para>

<para>
<path>nginx.conf</path>:
<example>
js_import http.js;

js_set $jwt_payload_sub http.jwt_payload_sub;

server {
    #...

    location /jwt {
        return 200 $jwt_payload_sub;
    }
}
</example>
</para>

<para>
<path>http.js</path>:
<example>
function jwt(data) {
    var parts = data.split('.').slice(0,2)
        .map(v=>Buffer.from(v, 'base64url').toString())
        .map(JSON.parse);
    return { headers:parts[0], payload: parts[1] };
}

function jwt_payload_sub(r) {
    return jwt(r.headersIn.Authorization.slice(7)).payload.sub;
    // when the token is provided as the "myjwt" argument
    // return jwt(r.args.myjwt).payload.sub;
}

export default {jwt_payload_sub};
</example>
</para>

</section>

</section>


<section id="http_proxying" name="HTTP Proxying">


<section id="fast_response" name="Returning Fastest Response from Proxy">

<para>
<path>nginx.conf</path>:
<example>
js_import http.js;

location /start {
    js_content http.content;
}

location /foo {
    proxy_pass http://backend1;
}

location /bar {
    proxy_pass http://backend2;
}
</example>
</para>

<para>
<path>http.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);
}

export default {content};
</example>
</para>

</section>


<section id="subrequests_chaining" name="Subrequests Chaining">

<para>
<path>nginx.conf</path>:
<example>
js_import http.js;

location /start {
    js_content http.content;
}

location /auth {
    proxy_pass http://auth_backend;
}

location /backend {
    proxy_pass http://backend;
}
</example>
</para>

<para>
<path>http.js</path>:
<example>
async function content(r) {
    try {
        let reply = await r.subrequest('/auth');
        let response = JSON.parse(reply.responseBody);
        let token = response['token'];

        if (!token) {
            throw new Error("token is not available");
        }

        let backend_reply = await r.subrequest('/backend', `token=${token}`);
        r.return(backend_reply.status, backend_reply.responseBody);

    } catch (e) {
        r.error(e);
        r.return(500);
    }
}

export default {content};
</example>
</para>

</section>

</section>


<section id="misc" name="Miscellaneous">


<section id="redirect" name="Internal Redirect">

<para>
<path>nginx.conf</path>:
<example>
js_import http.js;

location /redirect {
    js_content http.redirect;
}

location @named {
    return 200 named;
}
</example>
</para>

<para>
<path>http.js</path>:
<example>
function redirect(r) {
    r.internalRedirect('@named');
}

export default {redirect};
</example>
</para>

</section>

</section>

</article>