The problem is that when using js_body_filter directive nginx does not return response. In fact this is sample code which can be found in docs and examples. What am I missing?
Below all configuration together with Dockerfile on which this can be tested:
docker build -t test .
docker run -p 18080:8080 test
curl localhost:18080/index.html -v
Response from 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
I got the same issue and fixed it something like this:
As noted above it seems that using
js_body_filter
without any..._pass
the data from the file never gets read into memory. So in this fix if the filter didn't get any data and there is a request_filename set and the headers indicate that we are expected to send a non zero length body, we read the file ourselves.