{"id":41390,"date":"2021-04-24T06:41:49","date_gmt":"2021-04-23T21:41:49","guid":{"rendered":"https:\/\/jirak.net\/wp\/harnessing-the-power-and-convenience-of-javascript-for-each-request-with-the-nginx-javascript-module\/"},"modified":"2021-04-24T07:34:26","modified_gmt":"2021-04-23T22:34:26","slug":"harnessing-the-power-and-convenience-of-javascript-for-each-request-with-the-nginx-javascript-module","status":"publish","type":"post","link":"https:\/\/jirak.net\/wp\/harnessing-the-power-and-convenience-of-javascript-for-each-request-with-the-nginx-javascript-module\/","title":{"rendered":"Harnessing the Power and Convenience of JavaScript for Each Request with the NGINX JavaScript Module"},"content":{"rendered":"<p>Harnessing the Power and Convenience of JavaScript for Each Request with the NGINX JavaScript Module<\/p>\n<p>\n<\/p>\n<p>    table.nginx-blog, table.nginx-blog th, table.nginx-blog td {<br \/>\n        border: 2px solid black;<br \/>\n        border-collapse: collapse;<br \/>\n    }<br \/>\n    table.nginx-blog {<br \/>\n        width: 100%;<br \/>\n    }<br \/>\n    table.nginx-blog th {<br \/>\n        background-color: #d3d3d3;<br \/>\n        align: left;<br \/>\n        padding-left: 5px;<br \/>\n        padding-right: 5px;<br \/>\n        padding-bottom: 2px;<br \/>\n        padding-top: 2px;<br \/>\n        line-height: 120%;<br \/>\n    }<br \/>\n    table.nginx-blog td {<br \/>\n        padding-left: 5px;<br \/>\n        padding-right: 5px;<br \/>\n        padding-bottom: 2px;<br \/>\n        padding-top: 5px;<br \/>\n        line-height: 120%;<br \/>\n    }<br \/>\n    table.nginx-blog td.center {<br \/>\n        text-align: center;<br \/>\n        padding-bottom: 2px;<br \/>\n        padding-top: 5px;<br \/>\n        line-height: 120%;<br \/>\n    }<\/p>\n<p><em><strong>Editor<\/strong>&nbsp;&ndash; The blog post titled &#8220;Introduction to the NGINX JavaScript Module&#8221; redirects here. The post has been updated to use the NGINX JavaScript Module directives and features supported as of April&nbsp;2021.<\/em><\/p>\n<p>The NGINX JavaScript module (njs) became generally available as a stable module in NGINX Open Source&nbsp;1.11.10 and <span><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r12-released\/#r12-nginScript\">NGINX Plus R12<\/a><\/span>. <em>[The module was originally called nginScript, and that name appears in some older posts.]<\/em> We have been working steadily on NGINX&nbsp;JavaScript since its launch in <a href=\"https:\/\/www.nginx.com\/blog\/nginscript-new-powerful-way-configure-nginx\/\">September&nbsp;2015<\/a>, adding the features and language support included in the stable module.<\/p>\n<p>NGINX&nbsp;JavaScript is a unique JavaScript implementation for NGINX and NGINX&nbsp;Plus, designed specifically for server&#8209;side use cases and per&#8209;request processing. It extends NGINX configuration syntax with JavaScript code in order to implement sophisticated configuration solutions.<\/p>\n<p>The use cases are extensive, especially as the NGINX&nbsp;JavaScript module is available for both HTTP and TCP\/UDP protocols. Sample use cases for NGINX&nbsp;JavaScript include:<\/p>\n<ul>\n<li>Generating custom log formats with values not available from regular NGINX variables (for example, <a href=\"https:\/\/www.nginx.com\/blog\/diagnostic-logging-nginx-javascript-module\/\">diagnostic logging<\/a>)<\/li>\n<li>Modifying responses from proxied servers&lt;!&#8211; (<a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r24-released\/#njs-filtering\">response filtering<\/a>) &#8211;&gt;<\/li>\n<li>Implementing custom authentication schemes (for example, <a href=\"https:\/\/www.nginx.com\/blog\/validating-oauth-2-0-access-tokens-nginx\/\">OAuth 2.0 token introspection<\/a>)<\/li>\n<li>Parsing TCP\/UDP protocols for application&#8209;level sticky sessions (for example, <a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-iot-load-balancing-mqtt\/\">MQTT load balancing<\/a>)<\/li>\n<\/ul>\n<p>Before discussing NGINX&nbsp;JavaScript in more detail, let\u2019s first address two common misconceptions.<\/p>\n<h2>NGINX JavaScript Is Not Lua<\/h2>\n<p>The NGINX community has created several programmatic extensions over the years. At the time of writing, Lua is the most popular of these; it&#8217;s available as a <a target=\"_blank\" href=\"https:\/\/github.com\/openresty\/lua-nginx-module\" rel=\"noopener noreferrer\">module for NGINX<\/a> and a <a href=\"https:\/\/www.nginx.com\/products\/nginx\/modules\/\">supported, prebuilt third&#8209;party dynamic module<\/a> for NGINX&nbsp;Plus. The Lua module and add&#8209;on libraries provide deep integration with the NGINX core and a rich set of functionality, including a driver for Redis.<\/p>\n<p>Lua is a powerful scripting language. It, however, remains fairly niche in terms of adoption and is not typically found in the \u201cskillset toolbox\u201d of the frontend developer or DevOps engineer.<\/p>\n<p>NGINX&nbsp;JavaScript does not seek to replace Lua and it will be some time before NGINX&nbsp;JavaScript has a comparable level of functionality. The goal of NGINX&nbsp;JavaScript is to provide programmatic configuration solutions to the widest possible community by using a popular programming language.<\/p>\n<h2>NGINX JavaScript Is Not Node.js<\/h2>\n<p>NGINX&nbsp;JavaScript does not aim to turn NGINX or NGINX&nbsp;Plus into an application server. In simple terms, the use cases for NGINX&nbsp;JavaScript are akin to middleware, as the execution of JavaScript code happens between the client and the content. Technically speaking, while Node.js shares two things with the combination of NGINX&nbsp;JavaScript and NGINX or NGINX&nbsp;Plus&nbsp;&ndash; an <a href=\"https:\/\/www.nginx.com\/blog\/inside-nginx-how-we-designed-for-performance-scale\/\">event&#8209;driven architecture<\/a> and the JavaScript programming language&nbsp;&ndash; the similarities end there.<\/p>\n<p>Node.js uses the Google V8 JavaScript engine, whereas NGINX&nbsp;JavaScript is a bespoke implementation of the ECMAScript standards, designed specifically for NGINX and NGINX&nbsp;Plus. Node.js has a persistent JavaScript virtual machine (VM) in memory and performs routine garbage collection for memory management, whereas NGINX&nbsp;JavaScript initializes a new JavaScript VM and the necessary memory for each request and frees the memory when the request is completed.<\/p>\n<h2>JavaScript as a Server-Side Language<\/h2>\n<p>As mentioned above, NGINX&nbsp;JavaScript is a bespoke implementation of the JavaScript language. All other existing JavaScript runtime engines are designed to be executed within a web browser. The nature of client&#8209;side code execution is different from server&#8209;side code execution in many ways \u2013 from the availability of system resources to the possible number of concurrent runtimes.<\/p>\n<p>We decided to implement our own JavaScript runtime in order to meet the requirements of server&#8209;side code execution and fit elegantly with NGINX\u2019s request&#8209;processing architecture. Our design principles for NGINX&nbsp;JavaScript are these:<\/p>\n<ul>\n<li>\n<p><strong>Runtime environment lives and dies with the request<\/strong><\/p>\n<p>The NGINX&nbsp;JavaScript module uses single&#8209;threaded bytecode execution, designed for quick initialization and disposal. The runtime environment is initialized per request. Startup is extremely quick, because there is no complex state or helpers to initialize. Memory is accumulated in pools during execution and released at completion by freeing the pools. This memory management scheme eliminates the need to track and free individual objects or to use a garbage collector.<\/p>\n<\/li>\n<li>\n<p><strong>Non&#8209;blocking code execution<\/strong><\/p>\n<p>NGINX and NGINX&nbsp;Plus\u2019 event&#8209;driven model schedules the execution of individual NGINX&nbsp;JavaScript runtime environments. When an NGINX&nbsp;JavaScript rule performs a blocking operation (such as reading network data or issuing an external subrequest), NGINX and NGINX&nbsp;Plus transparently suspend execution of the associated NGINX&nbsp;JavaScript VM and reschedule it when the event completes. This means that you can write rules in a simple, linear fashion and NGINX and NGINX&nbsp;Plus schedule them without internal blocking.<\/p>\n<\/li>\n<li>\n<p><strong>Implement only the language support that we need<\/strong><\/p>\n<p>The specifications for JavaScript are defined by the <a target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/ECMAScript\" rel=\"noopener noreferrer\">ECMAScript<\/a> standards. NGINX&nbsp;JavaScript follows <a target=\"_blank\" href=\"https:\/\/www.ecma-international.org\/ecma-262\/5.1\/\" rel=\"noopener noreferrer\">ECMAScript 5.1<\/a> with some <a target=\"_blank\" href=\"https:\/\/www.ecma-international.org\/ecma-262\/6.0\/\" rel=\"noopener noreferrer\">ECMAScript 6<\/a> for mathematical functions. Implementing our own JavaScript runtime gives us the freedom to prioritize language support for server&#8209;side use cases and ignore what we don\u2019t need. We maintain a <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/njs\/compatibility.html\" rel=\"noopener noreferrer\">list of the currently supported language elements<\/a>.<\/p>\n<\/li>\n<li>\n<p><strong>Close integration with request&#8209;processing phases<\/strong><\/p>\n<p>NGINX and NGINX&nbsp;Plus process requests in distinct phases. Configuration directives typically operate at a specific phase and native NGINX modules often take advantage of the ability to inspect or modify a request at a particular phase. NGINX&nbsp;JavaScript exposes some of the processing phases through configuration directives to give control over when the JavaScript code is executed. This integration with the configuration syntax promises the power and flexibility of native NGINX modules with the simplicity of JavaScript code.<\/p>\n<p>The table below indicates which processing phases are accessible via NGINX&nbsp;JavaScript at the time of writing, and the configuration directives that provide it.<\/p>\n<table class=\"nginx-blog\" width=\"100%\">\n<tbody>\n<tr>\n<th width=\"57%\">Processing Phase<\/th>\n<th width=\"22%\">HTTP Module<\/th>\n<th>Stream Module<\/th>\n<\/tr>\n<tr>\n<td><code>Access<\/code>&nbsp;&ndash; Authentication and access control<\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_auth_request_module.html#auth_request\" rel=\"noopener noreferrer\"><code>auth_request<\/code><\/a> and <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_content\" rel=\"noopener noreferrer\"><code>js_content<\/code><\/a><\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/stream\/ngx_stream_js_module.html#js_access\" rel=\"noopener noreferrer\"><code>js_access<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td><code>Pre-read<\/code>&nbsp;&ndash; Read\/write payload<\/td>\n<td>N\/A<\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/stream\/ngx_stream_js_module.html#js_preread\" rel=\"noopener noreferrer\"><code>js_preread<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td><code>Filter<\/code>&nbsp;&ndash; Read\/write response during proxy<\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_body_filter\" rel=\"noopener noreferrer\"><code>js_body_filter<\/code><\/a><br \/><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_header_filter\" rel=\"noopener noreferrer\"><code>js_header_filter<\/code><\/a><\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/stream\/ngx_stream_js_module.html#js_filter\" rel=\"noopener noreferrer\"><code>js_filter<\/code><\/a><\/td>\n<\/tr>\n<tr>\n<td><code>Content<\/code>&nbsp;&ndash; Send response to client<\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_content\" rel=\"noopener noreferrer\"><code>js_content<\/code><\/a><\/td>\n<td>N\/A<\/td>\n<\/tr>\n<tr>\n<td><code>Log \/ Variables<\/code>&nbsp;&ndash; Evaluated on demand<\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_set\" rel=\"noopener noreferrer\"><code>js_set<\/code><\/a><\/td>\n<td><a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/stream\/ngx_stream_js_module.html#js_set\" rel=\"noopener noreferrer\"><code>js_set<\/code><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<\/ul>\n<h2 id=\"Getting-Started-with-NGINX-JavaScript\">Getting Started with NGINX JavaScript&nbsp;&ndash; A Real&#8209;World Example<\/h2>\n<p>NGINX&nbsp;JavaScript is implemented as a module that you can compile into an NGINX Open Source binary or dynamically load into NGINX or NGINX&nbsp;Plus. <a href=\"#njs-enable\">Instructions for enabling NGINX&nbsp;JavaScript<\/a> with NGINX and NGINX&nbsp;Plus appear at the end of this article.<\/p>\n<p>In this example we use NGINX or NGINX&nbsp;Plus as a simple reverse proxy and use NGINX&nbsp;JavaScript to construct access log entries in a specialized format, that:<\/p>\n<ul>\n<li>Includes the request headers sent by the client<\/li>\n<li>Includes the response headers returned by the backend<\/li>\n<li>Uses key&#8209;value pairs for efficient ingestion into and searching with log processing tools such as the ELK Stack (now called Elastic Stack), Graylog, and Splunk<\/li>\n<\/ul>\n<p>The NGINX configuration for this example is extremely simple.<\/p>\n<p><code data-gist-id=\"49e2f6f6b0a36ed9846dd63cddbd742a\" data-gist-file=\"rawheader_logging.conf\" data-gist-line=\"1-9\"><\/code><br \/>\n<!-- js_import  conf.d\/logging.js;                \t# Load JavaScript code from here\njs_set \t$access_log_headers logging.kvAccess; # Fill variable from JS function\nlog_format kvpairs $access_log_headers;      \t# Define special log format\n       \nserver {\n\tlisten 80;\n\troot \/usr\/share\/nginx\/html;\n\taccess_log \/var\/log\/nginx\/access.log kvpairs;\n}[\/rawheader_logging.conf] --><\/p>\n<p>As you can see, NGINX&nbsp;JavaScript code does not sit inline with the configuration syntax. Instead we use the <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_import\" rel=\"noopener noreferrer\"><code>js_import<\/code><\/a> directive to specify the file that contains all of our JavaScript code. The <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_set\" rel=\"noopener noreferrer\"><code>js_set<\/code><\/a> directive defines a new NGINX variable, <code>$access_log_headers<\/code>, and the JavaScript function that populates it. The <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_log_module.html#log_format\" rel=\"noopener noreferrer\"><code>log_format<\/code><\/a> directive defines a new format called <strong>kvpairs<\/strong> which writes each log line with the value of <code>$access_log_headers<\/code>.<\/p>\n<p>The <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_core_module.html#server\" rel=\"noopener noreferrer\"><code>server<\/code><\/a> block defines a simple HTTP reverse proxy that forwards all requests to <strong>https:\/\/www.example.com<\/strong>. The <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_log_module.html#access_log\" rel=\"noopener noreferrer\"><code>access_log<\/code><\/a> directive specifies that all requests will be logged with the <strong>kvpairs<\/strong> format.<\/p>\n<p>Let\u2019s now look at the JavaScript code that prepares a log entry.<\/p>\n<p><code data-gist-id=\"49e2f6f6b0a36ed9846dd63cddbd742a\" data-gist-file=\"logging.js\" data-gist-line=\"1-8\"><\/code><!-- function kvAccess(r) {\n\tvar log = `${r.variables.time_iso8601} client=${r.remoteAddress} method=${r.method} uri=${r.uri} status=${r.status}`;\n\tr.rawHeadersIn.forEach(h =&gt;--> log += ` in.${h[0]}=${h[1]}`);<br \/>\n\tr.rawHeadersOut.forEach(h =&gt; log += ` out.${h[0]}=${h[1]}`);<br \/>\n\treturn log;<br \/>\n}<\/p>\n<p>export default { kvAccess }[logging.js] &#8211;&gt;<\/p>\n<p>The return value from the <code>kvAccess<\/code> function&nbsp;&ndash; a log entry&nbsp;&ndash; is passed to the <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_js_module.html#js_set\" rel=\"noopener noreferrer\"><code>js_set<\/code><\/a> configuration directive in <strong>rawheader_logging.conf<\/strong>. Bear in mind that NGINX variables are evaluated on demand and this in turn means that the JavaScript function defined by <code>js_set<\/code> is executed when the value of the variable is required. In this example, <code>$access_log_headers<\/code> is used in the <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_log_module.html#log_format\" rel=\"noopener noreferrer\"><code>log_format<\/code><\/a> directive and so <code>kvAccess()<\/code> is executed at log time. Variables used as part of <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_map_module.html#map\" rel=\"noopener noreferrer\"><code>map<\/code><\/a> or <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/http\/ngx_http_rewrite_module.html#rewrite\" rel=\"noopener noreferrer\"><code>rewrite<\/code><\/a> directives (not illustrated in this example) trigger the corresponding JavaScript execution at an earlier processing phase.<\/p>\n<p>We can see this NGINX&nbsp;JavaScript&#8209;enhanced logging solution in action by passing a request through our reverse proxy and observing the resulting log file entry, which includes request headers with the <code>in.<\/code> prefix and response headers with the <code>out.<\/code> prefix.<\/p>\n<pre><code class=\"terminal\">$ <strong>curl http:\/\/127.0.0.1\/<\/strong>\r\n$ <strong>tail --lines=1 \/var\/log\/nginx\/access_headers.log<\/strong>\r\n2021-04-23T10:08:15+00:00 client=172.17.0.1 method=GET uri=\/index.html status=200 in.Host=localhost:55081 in.User-Agent=curl\/7.64.1 in.Accept=*\/* out.Content-Type=text\/html out.Content-Length=612 out.ETag=x22606339ef-264x22 out.Accept-Ranges=bytes\r\n<\/code><\/pre>\n<p>Much of the utility of NGINX&nbsp;JavaScript is a result of its access to NGINX internals. This example utilizes several <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/njs\/reference.html#http\" rel=\"noopener noreferrer\">properties of the request (<code>r<\/code>) object<\/a>. The Stream NGINX&nbsp;JavaScript module (for TCP and UDP applications) utilizes a <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/njs\/reference.html#stream\" rel=\"noopener noreferrer\">session object (<code>s<\/code>) <\/a> with its own set of properties. For other examples of NGINX&nbsp;JavaScript solutions for both HTTP and TCP\/UDP, see <a href=\"#Use-Cases-for-the-NGINX-JavaScript-Module\">Use Cases for the NGINX JavaScript Module<\/a>.<\/p>\n<p>We\u2019d love to hear about the use cases that you come up with for NGINX&nbsp;JavaScript&nbsp;&ndash; please tell us about them in the comments section below.<\/p>\n<hr \/>\n<h2>Use Cases for the NGINX JavaScript Module<\/h2>\n<p>Check out these blog posts to explore other HTTP and TCP\/UDP use cases for the NGINX JavaScript module:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/deploying-nginx-plus-as-an-api-gateway-part-2-protecting-backend-services\/#request-bodies\">Validating Request Bodies<\/a> in &#8220;Deploying NGINX&nbsp;Plus as an API Gateway, Part&nbsp;2: Protecting Backend Services&#8221;<!-- update published 2021-01-20 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/diagnostic-logging-nginx-javascript-module\">Diagnostic Logging with the NGINX JavaScript Module<\/a><!-- published 2020-09-29 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r22-released\/#njs\">Announcing <span>NGINX Plus R22<\/span><\/a>&nbsp;&ndash; Logging the exact set of headers sent by the client whenever an error is encountered<!-- published 2020-06-09 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r21-released\/#njs\">Announcing <span>NGINX Plus R21<\/span><\/a>&nbsp;&ndash; Chaining subrequests in a single code sequence without using callbacks; sending a copy of request headers to a security information and event management (SIEM) system<!-- published 2020-04-07 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/just-one-post-declarative-dns-with-f5-and-nginx-javascript\/\">Just One POST: Enabling Declarative DNS with F5 and the NGINX JavaScript Module<\/a><!-- published 2020-02-25 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/ota-updates-iot-devices-nginx\/\">Over-the-Air Updates to IoT Devices with NGINX<\/a><!-- published 2019-04-10 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r18-released\/#njs-enhancements\">Announcing <span>NGINX Plus R18<\/span><\/a>&nbsp;&ndash; Logging a hashed (masked) version of the client IP address instead of the real address<!-- published 2019-04-09 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/virtual-patching-with-nginx-javascript-module\/\">Virtual Patching with the NGINX JavaScript Module<\/a><!-- published 2018-11-19 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/batching-api-requests-nginx-plus-javascript-module\/\">Batching API Requests with NGINX Plus and the NGINX JavaScript Module<\/a><!-- published 2018-05-24 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r15-released\/#njs\">Announcing <span>NGINX Plus R15<\/span><\/a>&nbsp;&ndash; Issuing an HTTP request to two different backends simultaneously, then forwarding the first response and ignoring the second; adding data integrity to application cookies<!-- published 2018-04-10 --><\/li>\n<p><!-- NOTE: purposely not including \"NGINX and IoT: Adding Protocol Awareness for MQTT\" (\/blog\/nginx-and-iot-adding-protocol-awareness-for-mqtt\/), published 2017-11-06, in this list, because it is a transcript of a talk at Conf17 about material already covered in the two MQTT blogs in this list --><\/p>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/detecting-homepage-defacement-active-health-checks\/#scale-out-with-javascript\">Scaling Out Change Detection with JavaScript Hashing<\/a> in &#8220;Detecting Homepage Defacement With Active Health Checks&#8221;<!-- published 2017-10-11 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/tcp-load-balancing-udp-load-balancing-nginx-tips-tricks#nginScript\">Extending TCP\/UDP Load Balancing with nginScript<\/a> in &#8220;TCP\/UDP Load Balancing with NGINX: Overview, Tips, and Tricks&#8221;<!-- published 2017-04-14 --><\/li>\n<p><!-- \"nginScript\" is retained in the section name because the blog is a transcript of a talk --><\/p>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-iot-security-encrypt-authenticate-mqtt\/#mqtt-client-certs\">Using Client Certificates to Authenticate MQTT Clients<\/a> in &#8220;NGINX&nbsp;Plus for the IoT: Encrypting and Authenticating MQTT Traffic&#8221;<!-- published 2017-03-29 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-iot-load-balancing-mqtt\/#mqtt-session-persistence\">Load Balancing MQTT for Session Persistence with the NGINX JavaScript Module<\/a> in &#8220;NGINX&nbsp;Plus for the IoT: Load Balancing MQTT&#8221;<\/a><!-- published 2017-03-23 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/data-masking-user-privacy-nginscript\/\">Data Masking for User Privacy with the NGINX JavaScript Module<\/a><!-- published 2017-03-17 --><\/li>\n<p><!-- NOTE: purposely not including \"Announcing NGINX Plus R12\" (\/blog\/nginx-plus-r12-released\/), published 2017-03-14, in this list, because it simply announces GA of the module --><\/p>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/scaling-mysql-tcp-load-balancing-nginx-plus-galera-cluster\/#nginscript-logging-galera\">Advanced Logging with the NGINX JavaScript Module<\/a> in &#8220;Scaling MySQL with TCP Load Balancing and Galera Cluster&#8221;<\/a><!-- published 2016-11-16 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginx-plus-r11-released\/#r11-njs\">Announcing <span>NGINX Plus R11<\/span><\/a>&nbsp;&ndash; Searching for key patterns in a message in a MySQL protocol stream to identify the SQL operation<!-- published 2016-10-25 --><\/li>\n<li><a href=\"https:\/\/www.nginx.com\/blog\/nginscript-progressively-transition-clients-to-new-server\/\">Using the NGINX JavaScript Module to Progressively Transition Clients to a New Server<\/a><!-- published 2016-09-08 --><\/li>\n<\/ul>\n<p><\/em><!-- NOTE: list purposely doesn't include the following blogs tagged with \"NGINX JavaScript module\" because either they don't include a use case or use the pre-GA version of nginScript:\n- \"What\u2019s New in NGINX Plus R10?\" (\/blog\/https:\/\/www.nginx.com\/blog\/whats-new-nginx-plus-r10\/#nginScript), published 2016-09-23, because it is a webinar transcript that only briefly discusses the progressive transition use case covered in \"Using the NGINX JavaScript Module to Progressively Transition Clients to a New Server\"\n\n- \"nginx.conf 2016 Keynote by Owen Garrett: NGINX: Past, Present, and Future\" (\/blog\/owen-garrett-keynote-nginx-conf-2016\/), published 2016-09-21\n\n- \"Announcing NGINX Plus R10\" (\/blog\/nginx-plus-r10-released\/#r10-nginscript), published 2016-08-23 (even though has simple use case)\n\n- \"A New and Powerful Way to Configure NGINX: nginScript\" (\/blog\/nginscript-new-powerful-way-configure-nginx\/), published 2016-03-01\n\n- \"The Future of NGINX and NGINX Plus\" (\/blog\/future-nginx-nginx-plus\/#nginScript), published 2016-02-01\n\n- \"Holiday Reading List 2015\" (\/blog\/holiday-reading-list-2015\/), published 2015-12-21\n\n- \"nginx.conf 2015 Recap\" (\/blog\/nginx-conf-2015-recap\/), published 2015-10-01\n\n- \"nginScript: Why Are We Creating Our Own JavaScript Implementation?\" (\/blog\/nginscript-why-our-own-javascript-implementation\/), published 2015-09-28\n\n- \"Launching nginScript and Looking Ahead\" (\/blog\/launching-nginscript-and-looking-ahead\/), published 2015-09-23\n--><\/p>\n<h2 id=\"njs-enable\">Enabling NGINX&nbsp;JavaScript for NGINX and NGINX&nbsp;Plus<\/h2>\n<ul>\n<li><a href=\"#njs-nginx-plus-load\">Loading the NGINX&nbsp;JavaScript Module for NGINX&nbsp;Plus<\/a><\/li>\n<li><a href=\"#njs-oss-load\">Loading the NGINX&nbsp;JavaScript Module for NGINX Open Source<\/li>\n<li><a href=\"#njs-oss-compile\">Compiling NGINX&nbsp;JavaScript as a Dynamic Module for NGINX Open Source<\/a><\/li>\n<\/ul>\n<h3 id=\"njs-nginx-plus-load\">Loading the NGINX&nbsp;JavaScript Module for NGINX&nbsp;Plus<\/h3>\n<p>NGINX&nbsp;JavaScript is available as a free <a href=\"https:\/\/www.nginx.com\/products\/dynamic-modules\/\">dynamic module<\/a> for NGINX&nbsp;Plus subscribers. For loading instructions, see the <a target=\"_blank\" href=\"https:\/\/docs.nginx.com\/nginx\/admin-guide\/dynamic-modules\/nginscript\/\" rel=\"noopener noreferrer\">NGINX&nbsp;Plus Admin&nbsp;Guide<\/a>.<br \/>\n&lt;!&#8211; tmauro 6-Aug-2019 commented out and added pointer to Admin Guide<\/p>\n<ol>\n<li>\n<p>Obtain the module itself by installing it from the NGINX&nbsp;Plus repository.<\/p>\n<ul>\n<li>\n<p>For Ubuntu and Debian systems:<\/p>\n<p>[terminal]$ <strong>sudo apt&#8209;get install nginx-plus-module-njs<\/strong>[\/terminal]<\/li>\n<p>For RedHat, CentOS, and Oracle Linux systems:<\/p>\n<p>[terminal]$ <strong>sudo yum install nginx-plus-module-njs<\/strong>[\/terminal]\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Enable the module by including a <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/ngx_core_module.html#load_module\" rel=\"noopener noreferrer\"><code>load_module<\/code><\/a> directive for it in the top&#8209;level (&#8220;main&#8221;) context of the <strong>nginx.conf<\/strong> configuration file (not in the <code>http<\/code> or <code>stream<\/code> context). This example loads the NGINX&nbsp;JavaScript modules for both HTTP and TCP\/UDP traffic.<\/p>\n<p>[config]load_module modules\/ngx_http_js_module.so;<br \/>\nload_module modules\/ngx_stream_js_module.so;[\/config]\n<\/li>\n<li>\n<p>Reload NGINX&nbsp;Plus to load the NGINX&nbsp;JavaScript modules into the running instance.<\/p>\n<p>[terminal]$ <strong>sudo nginx -s reload<\/strong>[\/terminal]<\/li>\n<\/ol>\n<p> &#8211;&gt;<\/p>\n<h3 id=\"njs-oss-load\">Loading the NGINX&nbsp;JavaScript Module for NGINX Open Source<\/h3>\n<p>If your system is configured to use the official <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/linux_packages.html#mainline\" rel=\"noopener noreferrer\">prebuilt packages for NGINX Open Source<\/a> and your installed version is&nbsp;1.9.11 or later, then you can install NGINX&nbsp;JavaScript as a prebuilt package for your platform.<\/p>\n<ol>\n<li>\n<p>Install the prebuilt package.<\/p>\n<ul>\n<li>\n<p>For Ubuntu and Debian systems:<\/p>\n<pre><code class=\"terminal\">$ <strong>sudo apt-get install nginx-module-njs<\/strong><\/code><\/pre>\n<\/li>\n<li>\n<p>For RedHat, CentOS, and Oracle Linux systems:<\/p>\n<pre><code class=\"terminal\">$ <strong>sudo yum install nginx-module-njs<\/strong><\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Enable the module by including a <a target=\"_blank\" href=\"https:\/\/nginx.org\/en\/docs\/ngx_core_module.html#load_module\" rel=\"noopener noreferrer\"><code>load_module<\/code><\/a> directive for it in the top&#8209;level (&#8220;main&#8221;) context of the <strong>nginx.conf<\/strong> configuration file (not in the <code>http<\/code> or <code>stream<\/code> context). This example loads the NGINX&nbsp;JavaScript modules for both HTTP and TCP\/UDP traffic.<\/p>\n<pre><code class=\"config\">load_module modules\/ngx_http_js_module.so;\r\nload_module modules\/ngx_stream_js_module.so;<\/code><\/pre>\n<\/li>\n<li>\n<p>Reload NGINX&nbsp;Plus to load the NGINX&nbsp;JavaScript modules into the running instance.<\/p>\n<pre><code class=\"terminal\">$ <strong>sudo nginx -s reload<\/strong><\/code><\/pre>\n<\/li>\n<\/ol>\n<h3 id=\"njs-oss-compile\">Compiling NGINX&nbsp;JavaScript as a Dynamic Module for NGINX Open Source<\/h3>\n<p>If you prefer to compile an NGINX module from source:<\/p>\n<ol>\n<li>Follow <a href=\"https:\/\/www.nginx.com\/blog\/compiling-dynamic-modules-nginx-plus\/\">these instructions<\/a> to build either or both the HTTP and TCP\/UDP NGINX&nbsp;JavaScript modules from the <a target=\"_blank\" href=\"https:\/\/hg.nginx.org\/njs\/\" rel=\"noopener noreferrer\">open source repository<\/a>.<\/li>\n<li>Copy the module binaries (<strong>ngx_http_js_module.so<\/strong>, <strong>ngx_stream_js_module.so<\/strong>) to the <strong>modules<\/strong> subdirectory of the NGINX root (usually <strong>\/etc\/nginx\/modules<\/strong>).<\/a><\/li>\n<li>Perform Steps&nbsp;2 and&nbsp;3 in <a>Loading the NGINX&nbsp;JavaScript Module for NGINX Open Source<\/a>.<\/li>\n<\/ol>\n<p>The post <a rel=\"nofollow\" href=\"https:\/\/www.nginx.com\/blog\/harnessing-power-convenience-of-javascript-for-each-request-with-nginx-javascript-module\/\">Harnessing the Power and Convenience of JavaScript for Each Request with the NGINX JavaScript Module<\/a> appeared first on <a rel=\"nofollow\" href=\"https:\/\/www.nginx.com\">NGINX<\/a>.<\/p>\n<p>Source: <a href=\"https:\/\/www.nginx.com\/blog\/harnessing-power-convenience-of-javascript-for-each-request-with-nginx-javascript-module\/\" target=\"_blank\" rel=\"noopener\">Harnessing the Power and Convenience of JavaScript for Each Request with the NGINX JavaScript Module<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>Harnessing the Power and Convenience of JavaScript for Each Request with the NGINX JavaScript Module table.nginx-blog, table.nginx-blog th, table.nginx-blog td { border: 2px solid black; border-collapse: collapse; } table.nginx-blog { width: 100%; } table.nginx-blog th { background-color: #d3d3d3; align: left; padding-left: 5px; padding-right: 5px; padding-bottom: 2px; padding-top: 2px; line-height: 120%; } table.nginx-blog td { padding-left: 5px; padding-right: 5px; padding-bottom: 2px; padding-top: 5px; line-height: 120%; } table.nginx-blog td.center { text-align: center; padding-bottom: 2px; padding-top: 5px; line-height: 120%; } Editor&nbsp;&ndash; The blog post titled &#8220;Introduction to the NGINX JavaScript Module&#8221; redirects here. The post has been updated to use the NGINX JavaScript Module directives and features supported as of April&nbsp;2021. The NGINX JavaScript module (njs) became generally available as a stable module in NGINX Open Source&nbsp;1.11.10 and NGINX Plus R12. [The module was originally called nginScript, and that name appears in some <a class=\"mh-excerpt-more\" href=\"https:\/\/jirak.net\/wp\/harnessing-the-power-and-convenience-of-javascript-for-each-request-with-the-nginx-javascript-module\/\" title=\"Harnessing the Power and Convenience of JavaScript for Each Request with the NGINX JavaScript Module\">[ more&#8230; ]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[169],"tags":[652],"class_list":["post-41390","post","type-post","status-publish","format-standard","hentry","category-news","tag-nginx"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts\/41390","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/comments?post=41390"}],"version-history":[{"count":1,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts\/41390\/revisions"}],"predecessor-version":[{"id":41391,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/posts\/41390\/revisions\/41391"}],"wp:attachment":[{"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/media?parent=41390"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/categories?post=41390"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jirak.net\/wp\/wp-json\/wp\/v2\/tags?post=41390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}