繁体   English   中英

Node.js HTTP代理修改主体

[英]Node.js HTTP Proxy modify body

我想编程Node.js http代理,它将能够修改响应体。 到目前为止我做到了这一点:

http = require('http'),
httpProxy = require('http-proxy');

var proxy = httpProxy.createProxyServer();
http.createServer( function (req, res){
    //here I want to change the body I guess
    proxy.web(req, res, {
        target: req.url
    });
}).listen(8013);

我曾尝试使用res.write() ,但它给出了一个错误“无法在发送后设置标头”。 好吧,我不想改变标题,我想改变身体。
我该如何改变身体? 任何建议将不胜感激。

您收到该错误,因为写入HTTP响应必然会更改标头; Content-Length必须正确。

我解决这个问题的方法是缓冲整个响应体,使用cheerio进行解析和调整,然后将结果发送给客户端。

我通过猴子修补res.writeHeadres.writeres.end完成了这个,然后将请求交给http-proxy模块。

function requestHandler(req, res) {
    var writeHead = res.writeHead, write = res.write, end = res.end;

    res.writeHead = function(status, reason, headers) {
        if (res.headersSent) return req.socket.destroy(); // something went wrong; abort
        if (typeof reason == 'object') headers = reason;
        headers = headers || {};
        res.headers = headers;
        if (headers['content-type'] && headers['content-type'].substr(0,9) == 'text/html') { // we should only fiddle with HTML responses
            delete headers['transfer-encoding']; // since we buffer the entire response, we'll send a proper Content-Length later with no Transfer-Encoding.

            var buf = new Buffer();
            res.write = function(data, encoding) {
                if (Buffer.isBuffer(data)) buf = Buffer.concat([buf, data]); // append raw buffer
                else buf = Buffer.concat([buf, new Buffer(data, encoding)]); // append string with optional character encoding (default utf8)

                if (buf.length > 10 * 1024 * 1024) error('Document too large'); // sanity check: if the response is huge, bail.
                // ...we don't want to let someone bring down the server by filling up all our RAM.
            }

            res.end = function(data, encoding) {
                if (data) res.write(data, encoding);

                var $ = cheerio.load(buf.toString());

                // This is where we can modify the response.  For example,
                $('body').append('<p>Hi mom!</p>');

                buf = new Buffer($.html()); // we have to convert back to a buffer so that we can get the *byte count* (rather than character count) of the body

                res.headers['content-type'] = 'text/html; charset=utf-8'; // JS always deals in UTF-8.
                res.headers['content-length'] = buf.length;

                // Finally, send the modified response out using the real `writeHead`/`end`:
                writeHead.call(res, status, res.headers);
                end.call(res, buf);
            }


        } else {
            writeHead.call(res, status, headers); // if it's not HTML, let the response go through normally
        }
    }

    proxy.web(req, res, {
        target: req.url
    });

    function error(msg) { // utility function to report errors
        if (res.headersSent) end.call(res, msg);
        else {
            msg = new Buffer(msg);
            writeHead.call(res, 502, { 'Content-Type': 'text/plain', 'Content-Length': msg.length });
            end.call(res, msg);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM