r.requestBody/r.requestText/r.requestBuffer is undefined (NJS - JavaScript Modules on NGINX)

194 views Asked by At

I'm building a NGINX module with JavaScript, that read incoming requests and design whether to pass them to the proxy server, or to ignore them and return a "block.html" page as a response [kinda WAF].

The problem is when I try to access r.requestBody/r.requestText/r.requestBuffer (all three ways should give me the whole request), the variable was undefined.

Here are the JavaScript file (that for now has only "reading incoming messages" ability) and NGINX's configuration file:

waf.js

function main(r)
{
    return "Request: " + r.requestText;
}

export default { main };

/etc/nginx/conf.d/default.conf

js_path "/etc/nginx/njs";
js_import waf.js;

js_set $return_value_of_main_func_in_waf waf.main;
log_format ret_val $return_value_of_main_func_in_waf;

server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/njs_output.log ret_val;

    location / {
        js_content waf.main;
    }

    location /block.html {
        root   /usr/share/nginx/html;
    }

    location @app-backend {
        proxy_pass http://127.0.0.1:7777;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

njs_output.log

Request: undefined
Request: undefined
Request: undefined
Request: undefined

I tried to access other things in the r variable, like r.rawHeadersIn, and the output was fine:

Host,localhost,Connection,keep-alive,Cache-Control,max-age=0,sec-ch-ua,\x22Not?A_Brand\x22;v=\x228\x22, \x22Chromium\x22;v=\x22108\x22, \x22Google Chrome\x22;v=\x22108\x22,sec-ch-ua-mobile,?0,sec-ch-ua-platform,\x22Windows\x22,Upgrade-Insecure-Requests,1,User-Agent,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36,Accept,text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9,Sec-Fetch-Site,none,Sec-Fetch-Mode,navigate,Sec-Fetch-User,?1,Sec-Fetch-Dest,document,Accept-Encoding,gzip, deflate, br,Accept-Language,he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7,Cookie,security_level=0; security=low; PHPSESSID=ruioabebdprspfihjst4vu66he; session=9603a1c6-1fe4-4f93-be1a-68ad6a5738ed.vsLXilN0X5P1XWLCWBveUL1PkW8
1

There are 1 answers

0
Richard Nienaber On

I found an issue on the njs repo for this exact problem. It had a link to a blog post where the solution was to use the mirror directive.

e.g.

location / {
  # non-existent url but forces body to be read
  mirror /sbVE8Tvdrpjqf0D47mObQ97kzj7JPf
  js_content waf.main;
}