繁体   English   中英

node.js静态资产代理

[英]node.js static assets proxy

在我的Express应用中,我定义了这样一条路线:

// catch-all for static assets used by the UI
app.get('*', require('./lib/routes/static'));

我想将对静态文件的请求代理到其他地方运行的Web服务器。 为此,我编写了这段中间件:

// static.js
var request = require('request');

// static assets are served through another webserver to which we proxy
module.exports = function(req, res, next) {
  var host = process.env.UI_URL;
  var url = req.url;

  request(host + url, function(err, proxyRes) {
    if (err) {
      next(err);
    }
    // if the resource is a 404, serve `index.html` served by the `host` to enable using the `pushState` API in the browser
    if (proxyRes.statusCode === 404) {
      request(host).pipe(res);
    }
    // if the resource is not a 404, pipe the proxy response into the response to the original request
    else {
      proxyRes.pipe(res);
    }
  });
};

当我点击/asd/asd这样的虚假url时,应用程序毫无问题地获取了index.html文件。 因此404的逻辑分支按预期工作。 但是,当浏览器试图获取index.html引用的静态资源时,该请求最终将挂起,最终超时并产生“未接收到数据”。 我究竟做错了什么?

我可以看到以下问题:

proxyRes.pipe(res);

到节点到达该行的时间,整个响应流将已经完成。 显然,“请求”模块在调用处理程序函数之前会等待整个流。 否则,他们将无法通过body传递第三个参数。

最简单的解决方案是将已经通过“请求”保存的正文发送回去:

 request(host + url, function(err, proxyRes, body) {
   ...
   else {
     res.send(body);
   }
 }

,但这不适用于图像和其他二进制内容,因为主体已经被解码为字符串。

要使其与二进制资源一起使用,您需要从发出代理请求开始,缓冲来自代理的响应。 然后最终,根据响应,您可以决定将其流回浏览器。 您还需要传递标题,以便浏览器获取有关如何正确解码二进制正文内容的信息。

// static.js
var request = require('request'),
    stream = require('stream'),
    util = require('util');

function Buffer() {
  var pumping = true,
      queue = [],
      push = this.push.bind(this);

  function flush() {
    if (!pumping) return;
    while (queue.length && (pumping = push.apply({}, queue.shift())));
  }
  this._read = function () {
    pumping = true;
    flush();
  };
  this._write = function (chunk, encoding, callback) {
    queue.push([chunk, encoding]);
    callback();
  };
  stream.Duplex.call(this);
}
util.inherits(Buffer, stream.Duplex);

app.get('*', function(req, res, next) {
    var host = process.env.UI_URL,
        url = req.url,
        buffer = new Buffer();

  request(host + url, function(err, proxyRes, body) {
    if (err) {
      next(err);
    }
    if (proxyRes.statusCode === 404) {
      request(host).pipe(res);
    }
    else {
      res.set(proxyRes.headers);
      buffer.pipe(res);
    }
  }).pipe(buffer);
});

我希望您觉得这个例子有用。

暂无
暂无

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

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