代码之家  ›  专栏  ›  技术社区  ›  Amin Shah Gilani

如何在反向代理响应中的开头body标记后插入代码段

  •  0
  • Amin Shah Gilani  · 技术社区  · 8 年前

    我从上游获取以下格式的HTML页面:

    <!DOCTYPE html>
    <html lang="en" dir="ltr">
      <head>
        <meta charset="utf-8">
        ...
      </head>
      <body class="foo bar baz" data-foo="klaskassa" data-baz="lkaslkas" id="body">
        ...
      </body>
    </html>
    

    我有一个HTML片段,格式如下:

    <div class="my-snippet">
      ...
    </div>
    

    我想在开头后插入片段 body 标签,给我:

    <!DOCTYPE html>
    <html lang="en" dir="ltr">
      <head>
        <meta charset="utf-8">
        ...
      </head>
      <body class="foo bar baz" data-foo="klaskassa" data-baz="lkaslkas" id="body">
        <div class="my-snippet">
          ...
        </div>
        ...
      </body>
    </html>
    

    限制条件

    解决方案必须修改流,而不是在运行转换之前将主体收集到单个字符串中。该应用程序受内存限制,处理的请求太多,无法承受这样的性能损失。

    我尝试过的事情

    1. 哈蒙:显然你不能读写元素的内部。看见 this ,则, this this
    2. 习惯于 replacestream 如上所述 here 但这不起作用,事实上我的反应只是停止了。
    3. Transformer-proxy :但是 data 对象只能附加到。
    4. 我花了4个小时用Ruby编写了一个Rack应用程序,但后来我清醒过来,不再重写我的整个代码库。

    请:

    在答案中添加示例代码。因为这基本上是 connect 应用程序,我可以插入你给我的任何中间件。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Tarun Lalwani    8 年前

    所以我创建了一个简单的服务器启动一个代理服务器以及一个普通服务器

    var http = require('http'),
        httpProxy = require('http-proxy');
    
    
    proxy = httpProxy.createProxyServer({
        target:'http://localhost:9000',
    }).listen(8000); 
    
    //
    // Create your target server
    //
    http.createServer(function (req, res) {
        let data = 'request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2);
        res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': data.length });
        res.write(data);
        res.end();
    }).listen(9000);
    

    然后使用下面的

    $ curl "localhost:8000"
    request successfully proxied!
    {
      "accept": "*/*",
      "user-agent": "curl/7.54.0",
      "host": "localhost:8000",
      "connection": "close"
    }
    

    然后在我在下面找到的文档中

    自助式响应 真/假 ,如果设置为true,则不会调用任何webOutgoing传递,您有责任通过侦听和处理proxyRes事件来适当地返回响应

    所以像下面这样更新代码

    var http = require('http'),
        httpProxy = require('http-proxy');
    
    
    proxy = httpProxy.createProxyServer({
        target:'http://localhost:9000',
        selfHandleResponse: true
    }).listen(8000); // See (†)
    
    proxy.on('proxyRes', function(proxyRes, req, res) {
        if (proxyRes.headers["content-type"] && proxyRes.headers["content-type"].indexOf("text/plain") >=0) {
            // We need to do our modification
            if (proxyRes.headers["content-length"]) {
                //need to remove this header as we may modify the response
                delete proxyRes.headers["content-length"];
            }
            var responseModified = false;
            proxyRes.on('data', (data) => {
                let dataStr = "";
                if (!responseModified && (dataStr = data.toString()) && dataStr.indexOf("proxied!") >= 0) {
                    responseModified = true;
                    dataStr = dataStr.replace("proxied!", "proxied? Are you sure?")
                    res.write(Buffer.from(dataStr, "utf8"));
                    console.log("Writing modified data");
                } else {
                    res.write(data);
                    console.log("Writing unmodified data");
                }
            });
            proxyRes.on('end', (data) => {
                console.log("data ended")
                res.end();
            });
        } else {
            proxyRes.pipe(res)
        }
    });
    
    
    
    //
    // Create your target server
    //
    http.createServer(function (req, res) {
        let data = 'request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2);
        res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': data.length });
        res.write(data);
        res.end();
    }).listen(9000);
    

    然后再次测试

    $ curl "localhost:8000"
    request successfully proxied? Are you sure?
    {
      "accept": "*/*",
      "user-agent": "curl/7.54.0",
      "host": "localhost:8000",
      "connection": "close"
    }
    

    现在,服务器控制台上的输出如下

    Writing modified data
    data ended
    

    这并不能证实我们是否真的只修改了部分流。所以我修改了下面的代码

    http.createServer(function (req, res) {
        let data = 'request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2);
        res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': data.length * 5});
        res.write(data + data)
    
        setTimeout(() => {
            res.write(data + data + data);
            res.end();
        });
    
    }).listen(9000);
    

    并在浏览器中打开

    BrowserOutput

    正如您所看到的,数据在流中被替换,并且按照逻辑,替换只发生一次,流的其余部分按原样传递

    推荐文章