我正在尝试根据响应正文向 Nginx 中上游服务器的响应添加自定义响应标头。
为了简单起见,让这个自定义标头成为响应正文的 SHA1 哈希值。为了实现这一目标,我尝试使用 Nginx 的 njs 脚本模块。
我参考了 njs-examples 存储库中的示例。然而,这些示例将标题和正文部分分开处理,我正在努力将它们组合起来以实现我的目标。
这是我当前的配置:
# nginx.conf
load_module modules/ngx_http_js_module.so;
events {}
http {
js_path "/etc/nginx/njs/";
js_import main from hello.js;
# Configuration containing list of application servers
upstream app_servers {
server flask:5000;
}
server {
listen 80;
server_name localhost;
location / {
js_body_filter main.hello;
proxy_pass http://app_servers/;
}
}
}
# hello.js
function hello(r, data, flags) {
var val = data.length;
ngx.log(1, val);
r.headersOut["X-Hello"] = val;
r.sendBuffer(data, flags);
}
export default { hello };
但是,当我向 Nginx 服务器发送请求时,我在响应中看不到
X-Hello
标头。
有没有办法在 Nginx 中使用 njs 脚本来实现我的用例?如果没有,我应该考虑哪些替代方法,例如实现自定义 Nginx 模块?任何有关如何进行的建议或指导将不胜感激。
PS:我正在 Docker 容器上运行此设置,其中包含官方 nginx 映像以及一些用于热重载的脚本。如果需要的话,我也可以分享
Dockerfile
和 docker-compose.yml
。
Liam Crilly 在 Nginx 社区 slack 上回答。
这可能行不通,因为 NGINX 会发送响应 在读取整个正文之前向客户端发送标头。所以到时候 你已经阅读了响应正文,现在再修改就太晚了 标题。
您可以尝试使用
函数(使用js_header_filter
)但正如我所说,标头已经在 身体已收到。我认为这不会起作用res.length
再次思考这一点。你可以用预告片来做到这一点,只要 客户接受了。
使用
切换到分块 传输编码,删除内容长度标头,并定义一个 预告片。js_header_filter
使用
收集并散列正文,发送 body,然后发送我们上面定义的预告片中的哈希值。js_body_filter
好吧,所以我不能让这个下降:lolsob:这是一个解决方案,添加了一个 作为预告片的响应的 SHA-1 哈希值。不确定这是否能解决您的问题 问题,@Gaurav Jain,但我很高兴找到答案!
nginx.conf
片段
js_import conf.d/body.js;
js_set $body_hash body.get_hash;
server {
listen 80;
location / {
proxy_pass http://localhost:9001;
js_body_filter body.set_hash;
add_trailer Body-Hash $body_hash;
}
}
server {
listen 9001;
root /usr/share/nginx/html;
}
body.js
var hash = "";
var res = "";
var buf = 0;
function set_hash(r, data, flags) {
if (data.length) buf++;
res += data; // Collect the entire response,
if (flags.last) { // until we get the last byte.
try {
hash = require('crypto').createHash('sha1').update(res).digest('base64');
r.sendBuffer(res, flags);
ngx.log(ngx.INFO, `FILTERED ${res.length} bytes in ${buf} buffers`);
} catch (e) {
ngx.log(ngx.ERR, `ERROR ${e}`);
r.sendBuffer("", flags);
}
}
}
function get_hash() {
return hash;
}
export default { set_hash, get_hash }
Test
curl -i localhost
HTTP/1.1 200 OK
Server: nginx/1.25.2
Date: Wed, 13 Sep 2023 21:38:25 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Last-Modified: Tue, 15 Aug 2023 17:03:04 GMT
ETag: "64dbafc8-267"
Accept-Ranges: bytes
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Body-Hash: xRo/Dm3k64AtVjCUHD/Z4dDvrks=