Skip to content

NJS module preview. #652

Closed
Closed
@hongzhidao

Description

@hongzhidao

Hi, we are glad that the njs module development is nearly complete.
It's for extending Unit configuration. You are highly welcome to discuss.

Prerequisites

The patch can only be applied to the unit source code checked out from our mercurial repository.
To build Unit from source make sure you have all tools and software installed as described on our webiste.
To use mercurial simply install it using your favorite package managers like yum or apt.

apt install mercurial

Installation:

  1. njs

To build Unit with njs support, you need njs source code.
If you'd like to use Mercurial,

$ hg clone https://hg.nginx.org/njs

If you prefer Git,

$ git clone https://github.com/nginx/njs

Next, point to the resulting directory using the option --with-njs when configuring Unit's source code.

  1. Download the patch
wget -O unit-njs-module.patch https://gist.githubusercontent.com/tippexs/b6d167102f0bb06adcde304970e3a757/raw/37b67016a57578d0344737a5f7eec0f1bf194732/hg-unit-njs.patch
  1. Apply to patch
cd unit
hg import ../unit-njs-module.patch
  1. Configure
./configure --openssl --with-njs=../njs/
  1. Make
make

Document

The same options that accept variables can use template literals based on the njs scripting language. The following example composes a share path using two built-in Unit variables in an njs template:

{
    "listeners": {
        "*:8080": {
            "pass": "routes"
        }
    },
    "routes": [
        {
            "action": {
                "share": "`/www/html/${vars.host + vars.uri}`"
            }
        }
    ]
}      

Unit uses the njs library to evaluate the template expression and substitute the result at runtime. As the snippet above suggests, templates can refer to built-ins, custom variables, and other request properties:

args.*
Query string arguments Color=Blue is args.Color, and so on.

headers.*
Request header fields Content-Encoding is headers.Content-Encoding, and so on.

vars.*
Built-in and custom variables $host is vars.host, and so on.

Unit also provides a storage space for njs scripts to be used in your templates. Suppose you have a module saved as hellonjs.js:

var hellonjs = {}

hellonjs.hello = function(vars) {
    if ('unitvar' in vars) {
        return vars.unitvar;

    } else {
        return 'default';
    }
}

export default hellonjs

To use it with Unit, first upload it to the script storage at /scripts/:

# curl -X PUT --data-binary @hellonjs.js --unix-socket
   /path/to/control.unit.sock http://localhost/scripts/hellonjs

Next, add the uploaded script's name to /config/settings/auto_module for Unit to load the script:

# curl -X PUT -d '"hellonjs"' --unix-socket
   /path/to/control.unit.sock http://localhost/config/settings/auto_module

Now, the module can be used in njs templates. The following snippet creates a native Unit variable called unitvar and passes the vars object with the variable to the hello() function from the uploaded module:

{
    "match": {
        "uri": "~(?<unitvar>.*)"
    },
    "action": {
        "share": "`/www/html${hellonjs.hello(vars)}`"
    }
}

The function checks if unitvar exists and returns it; if it doesn't exist, the default value is used. Therefore, a request for a /test/ URI yields a share path of /www/html/test/.

For further reference, see the njs documentation.

Metadata

Metadata

Assignees

Labels

z-documentation-update-neededThis type of issues likely have a link to an issue in the Unit Docs repo

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions