代码之家  ›  专栏  ›  技术社区  ›  momo

Hook或callback在express中的第一个正文字节之前写入头值。js

  •  0
  • momo  · 技术社区  · 5 年前

    在express中的一些全局应用程序级中间件中。js(4.16.4)和节点。js(10.15.1)我想在任何中间件将正文的第一个字节写入响应对象之前,在最后一次机会向标头写入cookie。

    例如,想象有一个 beforeWriteBody 网上活动 Response 对象,我们可以这样做:

    res.on('beforeWriteResponseBody', res => {
        res.cookie('key', 'value');
    });
    

    认识到这个事件也可以被其他接收者听到,他们可以在这个函数之后写标题,但是,这对我非常有用,因为它可以帮助避免多次写这个cookie值,因为我事先不知道在写入响应体的实际第一个字节之前,cookie值可以在管道中的何处更新。

    Async可以,这样,如果此事件的任何侦听器尝试将字节写入响应体,而列表中还有其他侦听器要在之后调用,则可以暂停编写主体的侦听器,并调用其余的侦听器,然后,执行返回给body writer(虽然执行顺序可能很棘手,但如果只是强制执行侦听器附件的顺序,我仍然认为这可能是合理的)。

    我想在cookie中保留一些内容,但可以自由地多次修改该cookie,而无需写入多个重复的集cookie头,但无论写入了什么响应,即使是 res.redirect() 例如

    看看快车。js源代码,我看到了一个可能的切入点, `res.send() in response.js .

    在看了一会儿之后,它看起来像是我的 beforeWriteResponseBody 将在节点的第一个操作之前被调用 request.end .

    我看到node中有一些事件与我想要的非常接近,比如 finish 这是被触发的 之后 end 已经打过电话了。但我需要一个在之前触发的事件 res.write res.end 被叫来(或在他们被叫来之后,但在他们做任何工作之前)。

    0 回复  |  直到 5 年前
        1
  •  0
  •   bato3    5 年前

    Express不支持所需形式的挂钩/回调。

    总的来说,这种方法对你不好。JS允许您轻松覆盖任何函数,在这种情况下,您必须这样做:

    var app = express();
    
    let _end = express.response.end
    express.response.send = function() {
        if(!this.headersSent)
            console.log('can overwrite')
        _end.apply(this, arguments)
    }
    

    如果我没弄错的话,你可以用 headersSent ,否则您必须注意一次性调用技术,例如在 res .

        2
  •  0
  •   momo    5 年前

    无需等到最后一分钟才写入标题。每次你可能想写标题时,你都可以检查现有的标题并删除任何你不想要的。这为您提供了最后一次机会来确保标题是正确的,而无需将标题的多个副本放入响应中。

    即使有些标题的名称与您不想触摸的标题相同,也可以使用此功能。

    下面是一个非常粗略的实现,它可能会如何工作:

    const removeUnsentHeaderFromResponseHeaders = (res, headerName, exclusionFilter) => {
      let headerValues = res.get(headerName);
      if (!headerValues) {
        return;
      }
      if (!Array.isArray(headerValues)) {
        headerValues = [headerValues];
      }
      res.header(headerName, headerValues.filter(value => !exclusionFilter(value)));
    };
    

    下面是一个用法示例:

    // We want to set header 'My-Header', which can be set multiple times
    // but also want to remove any that I've already set during this request.
    // The ones my code has already set will contain `my-special-flag`.
    
    removeUnsentHeaderFromResponseHeaders(
        res,
        'My-Header',
        headerValue => headerValue.includes('my-special-flag')
    );
    res.set('My-Header', 'The full my-special-flag value that should overwrite');
    

    每次设置时都要这样做 My-Header 而且,您将避免在响应中发送额外的、无用的头值。