Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

利用 chunked 类型响应实现后台请求的监听 #127

Open
wayou opened this issue Jun 26, 2019 · 0 comments
Open

利用 chunked 类型响应实现后台请求的监听 #127

wayou opened this issue Jun 26, 2019 · 0 comments

Comments

@wayou
Copy link
Owner

wayou commented Jun 26, 2019

利用 chunked 类型响应实现后台请求的监听

Koa 中实现 chunked 数据传输 中介绍了如何在 Koa 中实现 Transfer-Encoding:chunked 类型的响应分片传输。这里来看一个应用场景。

假如我们想监听后台的请求,并将监听到的数据打印到页面。那么复用 chunked 类型的响应,我们只需要解决如何在页面 controller 中获取到别的 controller 被执行。

Koa 在 app 上有提供一个 emit 方法派发事件。这样,可以写一个中间件对请求进行拦截,并且派发事件。然后在在监听的地方可通 app.on 来响应事件,假设我们展示监听数据的页面 url 为 /monitor,在 /monitor 的 controller 中实现 chunked 数据响应,并且监听前面中间件发来的数据,然后不断输出到页面,达到了监听的效果。

实现后代码大概是这样子:

var Koa = require("koa");
var Router = require("@koa/router");

const PORT = 3000;

var app = new Koa();
var router = new Router();

const requestLogger = async (ctx, next) => {
  await next();
  ctx.app.emit(`response`, ctx);
};

app.use(requestLogger);

router.get("/", (ctx, next) => {
  ctx.body = "hello world";
});

router.get("/api", (ctx, next) => {
  ctx.body = {
    status: 0,
    foo: "bar"
  };
});

router.get("/test", (ctx, next) => {
  ctx.body = "hello test";
});

router.get("/monitor", async ctx => {
  const res = ctx.res;
  ctx.status = 200;
  res.setHeader("Content-Type", "text/html");
  res.write(`<h3>net monitor<h3>`);
  return new Promise(() => {
    ctx.app.on("response", data => {
      res.write(`
        <details>
        <summary>
        <a hre="${data.url}">${data.url}</a>
        </summary>
        <pre>${JSON.stringify(data.body, null, 2)}<pre>
        </details>
        `);
    });
  });
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(PORT);
console.info(`server started at http://localhost:${PORT}`);

运行效果:

利用 chunked 类型响应实现后台请求的监听

利用 chunked 类型响应实现后台请求的监听

问题

  • Transfer-Encoding:chunked 依赖于客户端与服务器之间建立的这个连接一直处于未完成的状态,只要服务端不主动 res.end() 掉。但服务器配置 keep alive 的时长设置会影响到该连接,超时后会断开,当然可以将限制调大。
  • 因为在 /monitor 这个页面中,它没有办法知道其他路由的到达与结束,所以这里复用了事件。使得在 /monitor 页面能够监听到其他 controller 的情况。但这种做法会面临内存增长过快的问题,因为连接和事件监听一直保持着。

但如果仅用于调试数据,比如查看页面发生了哪些请求,返回了什么数据,这种一次性暂时的需求,还是没问题的。

相关资源

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant