Error-tracking software doesn't catch hapi application errors if an incoming request gets prematurely closed

オープン
#4,567 コメント 2 件 リアクション 1 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

  • #4580 @puneetdixit200 による — マージされずにクローズ

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
説明が足りない
活発さ
停滞
技術スタック
javascript, node.js
領域
api, backend

調査の方向性

まず、request error event と onPreResponse フックを使用して、提供された Node.js の再現手順を実行します。次に、request lifecycle のドキュメントと、それに関連する request-abort の処理を調査します。中断されていないリクエストと比較し、意図されたエラー報告の動作を明らかにします。完了の条件は、プロジェクトとして中断されたリクエストに対する方針が合意され、コード変更が受け入れられる場合にリグレッションテストのカバレッジが追加されていることです。

索引モデルが issue の本文から書いたものです。

説明

bug
Runtime

Node.js

Runtime version

v25.7.0

Module version

v21.4.7

Last module version without issue

No response

Used with

Sentry, Rollbar, DataDog

Any other relevant information

Sentry, Rollbar, and DataDog support tracking errors in hapi applications, relying on either hapi's request error event or on onPreResponse lifecycle method. See:

What are you trying to achieve or the steps to reproduce?

Here is example code that reproduces an issue where an error thrown in a handler bypasses both the request error event and onPreResponse lifecycle method calls.

import Hapi from "@hapi/hapi";
import { setTimeout as sleep } from "node:timers/promises"

const server = Hapi.server({
    port: 3000,
    host: "localhost"
});

server.events.on({ name: "request", channels: ["error"] }, (request, event, tags) => {
    console.log("[server] on request error"); // NOT called
})

server.ext("onPreResponse", async (request, h) => {
   console.log("[server] onPreResponse"); // NOT called
   return request;
});

server.route({
    method: "GET",
    path: "/sleep/{seconds}/then-throw-error",
    handler: async (request, h) => {
        const { seconds } = request.params;
        for (let i = 0; i < seconds; i++) {
            console.log("[handler] Handling a request... (sleep %s)", i + 1);
            await sleep(1_000);
        }
        console.log("[handler] Throwing error");
        throw new Error("Boom!");
    }
});

await server.start();
console.log("[server] Running on %s", server.info.uri);

try {
    console.log("[fetch] Making a request");
    await fetch("http://localhost:3000/sleep/5/then-throw-error", { signal: AbortSignal.timeout(1_000) });
} catch (error) {
    if (error.name === "TimeoutError") {
        console.log("[fetch] Stopped waiting for the response");
    } else {
        console.log(error);
    }
}
What was the result you got?

Here is the output produced by the example code:

[server] Running on http://localhost:3000
[fetch] Making a request
[handler] Handling a request... (sleep 1)
[fetch] Stopped waiting for the response
[handler] Handling a request... (sleep 2)
[handler] Handling a request... (sleep 3)
[handler] Handling a request... (sleep 4)
[handler] Handling a request... (sleep 5)
[handler] Throwing error

Neither server.events.on({ name: "request", channels: ["error"] }, fn) nor server.ext("onPreResponse", fn) callback functions are called if the incoming request gets prematurely closed. However, if we increase the request timeout, e.g., AbortSignal.timeout(10_000), both callback functions will get called.

What result did you expect?

I'm not sure if the shown hapi behavior is a bug or if it works as intended, especially because the onPreResponse documentation mentions that it is “always called, unless the request is aborted.” Nevertheless, it's evident that there is existing error-tracking software that seems to be expecting to capture all errors using the approach. The fact that some errors are not getting captured is an issue. I would like to start a discussion to figure out a way forward on how to improve error tracking around aborted requests.

主要言語
JavaScript
スター
14.8k
フォーク
1.4k
平均マージ
12分
マージ済み PR(30日)
6

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

hapijs/hapi のほかの issue

hapijs/hapi の issue をすべて見る

似ている issue

JavaScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。