NJS FastCGI Response Filtering

Lance Dockins lance at wordkeeper.com
Thu Feb 17 05:02:55 UTC 2022

Is there a good way to reliably filter the response body from a FastCGI script via NJS?  I’ve done this with Lua before but NJS seems to be a bit different in terms of how the response body process works.  The end goal is basically that we just have a way to grab the text back from a FastCGI/PHP script and can then edit that response.  There’s a very specific end goal that we are trying to achieve that has to go through Nginx and can’t be done with PHP.

Initially I tried just using something like r.responseText since the call to FastCGI in Nginx should be its own subrequest but that doesn’t seem to work.  I’ve tried via js_body_filter but that keeps returning what looks like either encrypted or compressed data even though PHP compression is off and the FastCGI upstream is for a socket on the same server defined as another location in the same vhost (so the connection to the socket shouldn’t be suffering from encryption in that layer).

I’ve tried a few different options:

location = /index.php {
	include includes/fastcgi.conf;

	js_body_filter db.failed;

	fastcgi_pass unix:/var/run/php-fpm/account.sock;

With this being the function in db.js

function failed(r, data, flags){

r.error is just there to log the response as a test to see what it is structured like to code further from there.  That logs data like this:
2022/02/16 11:56:20 [error] 18589#18589: *61 js: �Z�r���) (ڕ��;�����LB��,��Y�;�rMa�3�b��!E�\��9/�C�KN�J�>%����()`fwv��%��A�,�u����n�4�{����?���^>;�ljI9�Dē&�&�LM�ܨ&�8�zҌ%S@Ű����	�S0E	Q��f����+�Ia�LA)PERf��lU���2�F�`���fKȩ�\^V�1Y

The response from the PHP file is just basic HTML so it shouldn’t look like this.

I’ve also tried using a js_content filter to try to use a subrequest to the PHP location block in the vhost, but that doesn’t seem to work at all.  It just errs out.  Here’s a very basic attempt to try to use that location.  I’ve tried this both with the named location block and a custom named internal block that I called /fastcgi to try to use the URI style syntax in the sub request.

The js_content filter is in a location block and is calling successfully but the code that it runs fails when trying to sub request to FastCGI.  Here’s a rough example that I’ve tried.

location = /fastcgi {
	include includes/fastcgi.conf;

	fastcgi_pass unix:/var/run/php-fpm/dbadmin.sock;

async function content(r){
    await r.subrequest('/fastcgi', {
        body: r.requestBuffer,
        method: r.method,
        detached: false
    }, function(r){
        return r.responseText;

That just seems to err like this:

2022/02/16 11:53:37 [error] 16995#16995: *54 FastCGI sent in stderr: "Access to the script '/home/account/www/fastcgi' has been denied (see security.limit_extensions)" while reading response header from upstream, client:, server:trequest: "GET /index.php HTTP/2.0", subrequest: "/fastcgi", upstream: "fastcgi://unix:/var/run/php-fpm/account.sock:"

The specific solution strategy doesn’t particularly matter as long as the end result is that we can receive and interact with the response body from a FastCGI request.

Does anyone have any ideas of how to just get the response body from a FastCGI request in NJS?

Any insights would be a huge help.

Lance Dockins

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20220216/e8674871/attachment.htm>

More information about the nginx mailing list