Как добавить промежуточное программное обеспечение Express в конце цепочки, которая вызывается несмотря ни на что (ответы OK / FAIL)? - PullRequest
0 голосов
/ 23 апреля 2019

Есть ли способ добавить промежуточное ПО в конец цепочки экспресса app или router, которая вызывается для отслеживания того, был ли отправлен ответ res / или нет?

Iозначает, независимо от того, если:

  • Отправляется ответ (строка, JSON и т. д.)
  • Статический обслуживаемый файл.
  • Файл не найден в статическомпапка.
  • A всеобщая обратная связь достигнут обратный вызов.
  • Достигнуто промежуточное ПО ошибки.

Пример

Например, если я хотел записать все ...

, был ли ответ успешным или нет , , т. Е. Он служил файлу через express.static( ... ) промежуточное программное обеспечение, некоторые данные, извлеченные из БД, или пользовательское промежуточное программное обеспечение, или еще раз ... если произошел сбой / возникла ошибка ... , есть ли способ вызвать обратный вызов в самом конце?

Насколько я понимаю, по замыслу, если статический файл успешно обслуживается (через express.static ), он не вызывает next(), поэтому tцепочка останавливается на этом.

И для любого специального промежуточного программного обеспечения, использующего res.send(), вы обычно не хотите вызывать next() впоследствии, так как это может вызвать некоторые нежелательные побочные эффекты (ошибки при повторном отправлении заголовков).

Для обработчиков ошибок это проще, поскольку здесь могут быть обнаружены все неудачные ответы.

Но как он может вывести как успешные, так и неудачные ответы?Может ли это быть что-то, что должно быть сделано без промежуточного программного обеспечения?

Ответы [ 2 ]

1 голос
/ 24 апреля 2019

Для этого существует концептуальная проблема с асинхронной архитектурой node.js и Express.Я опишу общую проблему, а затем расскажу о нескольких возможных обходных путях.

Во-первых, каждый обработчик Express может быть асинхронным.Таким образом, он вызывается и возвращается практически сразу, и никто за пределами этого мира не знает, ожидает ли он завершения какой-либо асинхронной операции, прежде чем в конечном итоге отправить свой ответ, или просто не смог ничего сделать.Вы буквально не можете отличить от внешнего мира.

Во-вторых, вы можете отслеживать заданный запрос, чтобы увидеть, вызывает ли он обработчик ошибок или отправляет ответ.Нет способа контролировать обработчик запроса, чтобы увидеть, не удалось ли ему что-либо отправить по причине, описанной выше - у вас нет способа узнать, ожидает ли он еще какой-то асинхронной операции.

Итак, вот лучшее, что я мог бы порекомендовать:

  1. Крюк res.end(), чтобы увидеть, когда его вызывают.Это указывает на то, что ответ выполнен (ошибка или успех).Вы можете увидеть пример этого в модуле express-afterware , который Медет связал в вышеприведенном комментарии.Общая идея заключается в том, что у вас будет свое промежуточное программное обеспечение где-то в самом начале цепочки, которое переопределяет res.end(), чтобы вы могли видеть, когда он вызывается.Это раннее промежуточное ПО просто устанавливало переопределение и вызывало next(), чтобы продолжить цепочку обработчиков.Затем, когда ответ закончится, ваше переопределение увидит, что res.end() вызван.Это должно работать для всех случаев, когда ответ отправляется.

  2. Затем вам все еще нужно обрабатывать случаи, когда ответ не отправляется (что, вероятно, связано с ошибочным кодом, поскольку все запросы должны получитьответ в конце концов).Единственный способ, которым я знаю, - это установить какое-то время ожидания для запроса.Вы можете использовать встроенный механизм server.setTimeout() или реализовать свой собственный в промежуточном программном обеспечении (то же промежуточное программное обеспечение, которое описано в шаге 1).Затем, после определенного вами тайм-аута, если ответ еще не отправлен, вы вступаете во владение и отправляете какой-нибудь ответ об ошибке.

  3. Установите свои собственные промежуточные программы ошибок в начале цепочки, которая будетувидеть и записать все ошибки.Обратите внимание, что res.end() будет по-прежнему вызываться, поэтому поведение на шаге 1 будет по-прежнему вызываться даже для ошибок (ответы об ошибках по-прежнему вызывают res.end()).

0 голосов
/ 24 апреля 2019

Решение, с которым я столкнулся, в итоге немного отличалось от этого на @ idbehold , но в двух словах, в самом верху цепочки промежуточного программного обеспечения для экспресс-приложений, у меня было перехватить обратный вызов к событию finish объекта res Response, которое вызывается для большинства (всех?) кодов состояния HTTP, необходимых для отслеживания успешно обработанного запроса.

app.use( ( req, res, next ) => {
    res.on( 'finish', () => {
        var codeStr = String( res.statusCode );
        codeStr = codeStr[res.statusCode < 400 ? 'green' : 'red'];
        var output = [req.method.green, req.fullUrl().green, codeStr];
        trace( output.join( ' ' ) );
    } );

    next();
});

Теперь я могу получить такие вещи, как:

enter image description here

EDIT

Хорошо! Таким образом, при условии, что у вас также есть обработчик ошибок в «конце» цепочки промежуточного программного обеспечения, который обслуживает что-то с кодом ошибки 404, который вызовет событие finish для объекта res.

Пример такого обработчика ошибок:

app.use( ( err, req, res, next ) => {
    trace( "Error!".red );
    trace( err );

    res.status( 404 ).send(); // Triggers 'finish' on res.
})
...