skip to Main Content

This is the first time me playing with Nginx & njs.

I am trying to find a way to get the value from the JSON request and pass it as a new header to the upstream.

I have the following function:

function extract (r) {
   var json = JSON.parse(r.requestText);
   var sessionid = json["sessionId"];
   return sessionid;
}

And then:

js_set $sessionid http.extract;

I cannot assign the result of my function to the $sessionid variable which then I will use to pass to the upstream server:

proxy_set_header Cookie "mycookie=$sessionid";

When I send the curl command, the /var/log/nginx/error.log gives me:

2024/11/28 01:10:20 [error] 64724#64724: *455 js exception: SyntaxError: Unexpected token at position 0
    at JSON.parse (native)
    at extract_sessionid (/etc/nginx/njs/http.js:3)

The r.requestText is a JSON:

{ "sessionId":"F105" }

The value "F105" would be used to proxy add header.

Any idea?

Thank you.

2

Answers


  1. From the documentation for requestText/requestBuffer:

    The property is available only in the js_content directive.

    Login or Signup to reply.
  2. As being noted, the requestBuffer/requestText properties are available only in the js_content directive. Still, there is no reason to give up 🙂 Here are two methods that should help you achieve the result you’re looking for.

    • Analyze the requestText property using the js_content location content handler and then jump to another location for further request processing:

      nginx.conf

      js_import /path/to/extract_json_field.js;
      server {
          ...
          location / {
              # `$session_id` variable needs to be preinitialized
              set $session_id "";
              js_content extract_json_field.parse_request_text;
          }
          location @main {
              ... # all the other `proxy_set_header` directives, etc.
              proxy_set_header Cookie "mycookie=$session_id";
              proxy_pass http://backend;
          }
      }
      

      extract_json_field.js

      function parse_request_text(r) {
          try {
              let json = JSON.parse(r.requestText);
              r.variables.session_id = json['sessionId'] || '';
          } catch (e) {
              r.error('JSON.parse exception');
          }
          r.internalRedirect('@main');
      }
      
      export default { parse_request_text }
      
    • Use the mirror directive to populate $request_body built-in nginx variable during the PREACCESS request processing phase. This allows you to use r.variables.request_body in place of the requestText property (inspired by this example):

      nginx.conf

      js_import /path/to/extract_json_field.js;
      server {
          ...
          js_set $session_id extract_field.parse_request_body;
          location / {
              ... # all the other `proxy_set_header` directives, etc.
              proxy_set_header Cookie "mycookie=$session_id";
              mirror /_get_request_body;
              proxy_pass http://backend;
          }
          # Dummy location used to populate `$request_body` variable
          location /_get_request_body {
              internal;
              return 204;
          }
      }
      

      extract_json_field.js

      function parse_request_body(r) {
          let json = {};
          try {
              json = JSON.parse(r.variables.request_body);
          } catch (e) {
              r.error('JSON.parse exception');
          }
          return json['sessionId'] || '';
      }
      
      export default { parse_request_body }
      

    If you’d like njs, I can recommend two excellent resources:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search