nitro icon indicating copy to clipboard operation
nitro copied to clipboard

Missing afterReponse hook when an error happens

Open huang-julien opened this issue 1 year ago • 1 comments

Environment

windows 11 nitro 2.9.6 h3 1.11 - 1.12

Reproduction

https://stackblitz.com/edit/unjs-nitro-starter-bbtnhb?file=server%2Froutes%2Fthrow.ts,server%2Froutes%2Findex.ts,server%2Fplugins%2Flog.ts,package.json&title=Nitro%20Starter

index return an error and /throw throws an error. In both case, afterResponse isn't called

Describe the bug

There's a bug where throwing error in handlers prevent the afterResponse from being called.

Additional context

No response

Logs

No response

huang-julien avatar Jun 24 '24 21:06 huang-julien

Upstream issue from https://github.com/unjs/h3/issues/790

huang-julien avatar Jun 25 '24 08:06 huang-julien

Digging through the code, it looks like the root cause may be that nitro's onError handler actually sends the response https://github.com/nitrojs/nitro/blob/v2/src/runtime/error.ts#L82

This marks the event as handled, so h3 will not call the beforeResponse/afterResponse hooks https://github.com/unjs/h3/blob/v1/src/adapters/node.ts#L73

Maybe a solution could be to also trigger those hooks within the error handler, before and after the send calls.

cjpearson avatar Mar 24 '25 16:03 cjpearson

Moving to the Web APIs for the server, after response stagge cannot be stably hooked on since the platform handles the response object when returned.

Two possible workarounds (although I don't suggest either unless you really have to):

  • Wrap Response.body stream and wait for it to be finished
  • Use event.node?.res.on("finished") hook

For an operation like sending error reports that might need to be ongoing until after response without blocking it, event.waitUntil can be used.

pi0 avatar Mar 24 '25 18:03 pi0

Could this still be fixed for beforeResponse or will that also be removed?

cjpearson avatar Mar 24 '25 19:03 cjpearson

beforeResponse should work with the error handler in v2. Nitro hasn't migrated yet (on it) but if you can reproduce any issue with it and h3 only please feel free to open new issue 👍🏼

pi0 avatar Mar 24 '25 19:03 pi0

https://github.com/nitrojs/nitro/issues/3254

cjpearson avatar Mar 25 '25 12:03 cjpearson

@pi0 how would you use event.waitUntil to update metrics?

I'm using afterResponse hook to increment prometheus metrics, something like this

httpRequestCount.inc({ method: req.method, route, status_code: res.statusCode })
httpRequestDuration.observe({ method: req.method, route, status_code: res.statusCode }, durationInSeconds)

if (res.statusCode >= 400) {
	httpRequestErrors.inc({ method: req.method, route, status_code: res.statusCode })
}
})

but when an error occurs, as mentioned in this issue the counters don't increase. Is there a workaround for that?

canidam avatar Aug 15 '25 07:08 canidam