Nginx在使用js_body_filter njs指令时不返回响应体



问题是,当使用js_body_filter指令nginx不返回响应。实际上,这是可以在文档和示例中找到的示例代码。我错过了什么?

在所有配置下面,以及可以测试的Dockerfile:

docker build -t test .
docker run -p 18080:8080 test
curl localhost:18080/index.html -v

curl响应:

*   Trying 127.0.0.1:18080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 18080 (#0)
> GET /index.html HTTP/1.1
> Host: localhost:18080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.21.1
< Date: Wed, 22 Sep 2021 16:01:05 GMT
< Content-Type: text/html
< Content-Length: 5
< Last-Modified: Wed, 22 Sep 2021 15:55:24 GMT
< Connection: keep-alive
< ETag: "614b51ec-5"
< Expires: Wed, 22 Sep 2021 16:01:04 GMT
< Cache-Control: no-cache
< Accept-Ranges: bytes
<
* transfer closed with 5 bytes remaining to read
* Closing connection 0
curl: (18) transfer closed with 5 bytes remaining to read

default.conf

js_import envsubst from conf.d/envsubst.js;
server {
listen 8080;
location / {
proxy_buffering off;
js_body_filter envsubst.process;
root /etc/nginx/www;
index  index.html index.htm;
try_files $uri $uri/ /index.html;
expires -1;
}
error_page   500 502 503 504  /50x.html;
location = /50x.html {
root /etc/nginx/www;
}
}
server {
listen 8085;
location /health {
access_log off;
return 200 "";
}
}

envsubst.js

var res = "";
function process(r, data, flags) {
res += data;
if (flags.last) {
r.sendBuffer(res.toLowerCase(), flags);
}
}
export default { process };

nginx.conf


worker_processes  auto;
error_log  /var/log/nginx/error.log notice;
pid        /tmp/nginx.pid;
load_module modules/ngx_http_js_module.so;
events {
worker_connections  1024;
}

http {
proxy_temp_path /tmp/proxy_temp;
client_body_temp_path /tmp/client_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
include       /etc/nginx/mime.types;
default_type  application/octet-stream;
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log  /var/log/nginx/access.log  main;
sendfile        on;
#tcp_nopush     on;
keepalive_timeout  65;
#gzip  on;
include /etc/nginx/conf.d/*.conf;
}

index . html

test

Dockerfile

FROM nginxinc/nginx-unprivileged:1.21.1-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY default.conf /etc/nginx/conf.d/default.conf
COPY envsubst.js /etc/nginx/conf.d/envsubst.js
RUN  mkdir /etc/nginx/www 
COPY index.html /etc/nginx/www/index.html

我得到了同样的问题,并修复了它像这样:

var res = "";
function process(r, data, flags) {
res += data;
if (flags.last) {
if (res.length == 0 && r.variables.request_filename && r.headersOut["Content-Length"] != 0) {
// running this filter on files causes empty responses
// if we have a filename we read it and send it to the client
var fs = require('fs');
res = fs.readFileSync(r.variables.request_filename);
}
r.sendBuffer(res.toLowerCase(), flags);
}
}
export default { process };

如上所述,似乎使用js_body_filter而不使用..._pass,文件中的数据永远不会被读入内存。所以在这个修复中,如果过滤器没有得到任何数据,并且有一个request_filename集合,并且头指示我们期望发送一个非零长度的主体,我们自己读取文件。