在nginx中为来自上游服务器的响应添加自定义头

qvk1mo1f  于 2023-10-17  发布在  Nginx
关注(0)|答案(1)|浏览(188)

我试图添加一个自定义的响应头响应从上游服务器在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容器上运行这个安装程序,使用official nginx image和一些用于热重装的脚本。如果需要,我也可以共享Dockerfiledocker-compose.yml

rsaldnfx

rsaldnfx1#

由利亚姆克里利在Nginx community slack上的Ancarter。
这可能不起作用,因为NGINX将在阅读整个主体之前将响应头发送给客户端。所以当你读到响应体的时候,修改头已经太晚了。
您可以尝试使用js_header_filter函数(使用res.length),但正如我所说,在接收主体之前已经发送了头。我不认为它会工作
再想想这个。你可以用拖车来做,只要客户接受。
使用js_header_filter切换到分块传输编码,删除内容长度头,并定义尾部。
使用js_body_filter收集并散列正文,发送正文,然后在我们上面定义的trailer中发送散列。
好吧,所以我不能让这个下降: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=

相关问题