2

I have some nginx variables defied in my server_content.conf file is there a way we can access it in my .js file? servercontent.conf ... set $debug_log 'off'; ...

logging.js if(ngx.var.debug_log = 'on') .. do something

Ivan Shatsky
  • 13,267
  • 2
  • 21
  • 37
Aman
  • 21
  • 4

1 Answers1

1

Using the SSI

The first way of how this can be solved is to use the Server Side Includes module.

Here is a brief example:

  • nginx configuration fragment:
set $debug_log on;
location / {
    ssi on;
    ssi_types application/javascript;
    ...
}
  • logging.js example
var logging = '<!--# echo var="debug_log" -->';
console.log("Debug status detected via SSI substitution is", logging);

Read the module documentation to find out all the available features.

For the security purposes, if there is the only JS file you want to be able to receive some data from nginx, declare an individual location for this file (this will also speed-up all the other JS content being served), for example if its URI is /js/logging.js:

location / {
    ... # default location
}
location = /js/logging.js {
    # do not cache this file at the client side
    add_header Cache-Control "no-cache, no-store, must-revalidate";
    ssi on;
    ssi_types application/javascript;
}

Using the AJAX endpoint

The second way to solve this is to define an AJAX endpoint with the nginx configuration:

location = /getdebug {
    default_type application/json;
    return 200 '{"logging":"$debug_log"}';
}

Now the $debug_log nginx value can be acquired using the AJAX call from the browser-side JavaScript code:

const xhr = new XMLHttpRequest();
xhr.open('GET', '/getdebug');
xhr.responseType = 'json';
xhr.onload = function() {
    if (this.status == 200) {
        console.log('Debug status detected via AJAX request is', this.response.logging);
    }
};

Update 1

Turns out the whole question was about njs rather than browser-side JavaScript. In theory this can be achieved via the subrequests API using responseBuffer or even responseText subrequest object properties. You can look at the Setting nginx var as a result of async operation examples, especially this one, using some kind of more simple plain text endpoint:

location = /getdebug {
    default_type text/plain;
    return 200 $debug_log;
}

Unfortunately I'm not familiar with the njs (I use the lua-nginx-module for the similar purposes) and don't know if there is a more straight way to do it (which is probably exists).

Additionally, if you are trying to use Node modules with njs, make sure you read the Using node modules with njs documentation chapter.


Update 2

All nginx variables (which are evaluated on per-request basis) are available in the njs code via r.variables{} HTTP Request object property, e.g.

if (r.variables.debug_log == 'on') {
    ... do something
}
Ivan Shatsky
  • 13,267
  • 2
  • 21
  • 37
  • js file complains with this line of code var logging = ""; – Aman May 19 '22 at 13:17
  • The `` fragment should be changed to the actual nginx `$debug_log` variable value via the SSI mechanism. If it doesn't happen, you either did not enable it via `ssi on;`, did not specify the correct MIME type via `ssi_types` or did it in the wrong `location` block. I checked this answer before posting it and can confirm it is workable. – Ivan Shatsky May 19 '22 at 13:21
  • I created an .html location block and works perfectly fine. but js shows syntax error – Aman May 19 '22 at 14:43
  • You'd better show your nginx config, at least the relevant part. Did you add the `ssi_types application/javascript;` to it before trying JS? Can you check what actual MIME type nginx returns with the JS file? Maybe it is something different, say `text/javascript` or `x-application/javascript` (check the network tab of the browser development tools). Look at the `Content-Type` response header value. – Ivan Shatsky May 19 '22 at 14:47
  • here is the .conf file set $debug_log 'on'; location = /invoke { ssi on; ssi_types application/javascript; proxy_intercept_errors on; return 200 "gateway is running from invoke!"; } I see in postman Content-Type : text/plain and this is how js part looks like js_import node_modules/logging.js; js_set $function logging.someFunctionName; What I am trying to do is fetch debug_log value inside my logging.someFunctionName. My VS complains of syntax errors when I add this var logging = ; I am relatively new to nginx and js. – Aman May 19 '22 at 15:24
  • Was all of this about nginx njs rather than browser client-side javascript??? – Ivan Shatsky May 19 '22 at 16:13
  • yes that's correct nginx and njs – Aman May 19 '22 at 19:01
  • Than why do you not mention it in your question? I updated the answer with some links that may be helpful and add the "njs" tag to your question, however njs is not my area of competency. – Ivan Shatsky May 22 '22 at 15:25
  • @Aman Check the second update to the answer. – Ivan Shatsky May 26 '22 at 13:47
  • I made the changes using Update 1 and 2 both. I am using a /debug json endpoint for POST request which will override the flag for few seconds and fetch it in the node_module. Works like a charm. Thanks a lot for the help! highly appreciate it! – Aman May 27 '22 at 14:18
  • If you find the answer helpful, you mau consider to mark it as [accepted](https://stackoverflow.com/tour#:~:text=The%20person%20who%20asked%20can%20mark%20one%20answer%20as%20%22accepted%22.) (however, there is no obligation to do it). – Ivan Shatsky Jun 01 '22 at 20:30