Setup prom-client metrics collector server middleware to capture all routes
I want to define a middleware to collect metrics of api routes. With the help of AI I came up with such server/middleware:
How can I make something similar to
await next()
to let Nuxt process the request, and execute the code below after the request is finished?11 Replies
Hi @lazygopher. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
In Nuxt server middleware (in the
Docs: Server Middleware This means you cannot "await" the next handler and then run code after the response is sent in the same way as Express. However, Nuxt provides a way to run asynchronous code after the response is sent using
You cannot use
Docs: Nitro App Hooks
Docs: Server Middleware ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
server/middleware/
directory), you do not have access to a next()
function like in Express or Koa. Instead, Nuxt's middleware system is based on h3, and the middleware handler is expected to either:
- Do some work and not return anything (to let the request continue), or
- Return a value (which will terminate the request and send the response immediately)Docs: Server Middleware This means you cannot "await" the next handler and then run code after the response is sent in the same way as Express. However, Nuxt provides a way to run asynchronous code after the response is sent using
event.waitUntil
. This is useful for background tasks, but it does not allow you to measure the time taken by the request handler itself, since your middleware runs before the handler and not after.
If you want to collect metrics after the response is sent, you should use Nitro's lifecycle hooks, specifically the afterResponse
hook. This hook is called after the response is sent, and you have access to the event and response body, which is ideal for metrics collection.
Example using a Nitro plugin:
- The request
hook records the start time.
- The afterResponse
hook calculates the duration and records the metrics.
Summary:You cannot use
await next()
in Nuxt server middleware. For post-response logic like metrics, use Nitro's afterResponse
hook in a server plugin instead of middleware.Docs: Nitro App Hooks
Docs: Server Middleware ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai it looks like when the server returns an error (status code > 400) the hooked function in "afterResponse" is not executed:
nitroApp.hooks.hook("afterResponse", (event) => { .. })
I need the "afterResponse" to be executed all the time, even for errors. The reason is I increment counters of http total requests and duration
Let me check the knowledge base for you again. One moment! :books:
----------------------
Based on the official Nuxt and Nitro documentation, the
According to the official documentation,
afterResponse
hook in a Nitro plugin is designed to be called after sending the response, regardless of whether the response is a success or an error. The documentation for Nitro App Hooks (runtime, server-side) lists afterResponse
as:
Called after sending the response.There is no explicit mention in the documentation that
Arguments:event, { body }
afterResponse
would be skipped for error responses. In fact, the hook is intended to run after all responses, including those with error status codes, since it is triggered after the response is sent to the client.
If you are observing that afterResponse
is not being called for error responses, this is unexpected based on the official documentation. It could be due to:
- An unhandled exception that prevents the hook from being reached.
- The error is thrown at a level that bypasses the normal request lifecycle (for example, a fatal server crash).
However, the documentation does not provide details about any such limitations or exceptions. If you are experiencing this behavior, it may be a bug or an edge case not covered in the documentation. You may want to check for unhandled exceptions in your code or consult the Nuxt issue tracker for similar reports.
Summary:According to the official documentation,
afterResponse
should be executed for all responses, including errors. If it is not, the knowledge sources do not provide an explanation, and this may require further investigation or reporting as a potential issue in Nuxt/Nitro.
Docs: Nitro App Hooks (runtime, server-side)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai Is this true even if I throw an error in my server api code?
throw createError({
statusCode: 401,
statusMessage: "...",
})
Let me check the knowledge base for you again. One moment! :books:
----------------------
Based on the official Nuxt and Nitro documentation, the
afterResponse
hook is described as being called "after sending the response," and there is no explicit exception mentioned for error responses, including those generated by throwing createError
in your server API code. The documentation does not state that throwing an error (such as with createError
) would prevent afterResponse
from being executed. Therefore, according to the documentation, afterResponse
should be called even when you throw an error in your server API code — for example:
However, the knowledge sources do not provide a concrete example or explicit confirmation of this behavior for errors thrown with createError
. If you are observing different behavior in practice, it may be due to an undocumented edge case or a bug, but the documentation itself does not mention such a limitation — it implies that afterResponse
should always run after a response is sent, regardless of status code or error origin Docs: Nitro App Hooks (runtime, server-side).
If you need absolute certainty for your use case, you may want to test this behavior directly or consult the Nuxt issue tracker for any related reports.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai I found an issue describing exactly my case - https://github.com/nitrojs/nitro/issues/2560 apparently when error occurs the "afterResponse" hook is not executed.
GitHub
Missing afterReponse hook when an error happens · Issue #2560 · n...
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%2Flo...
Let me check the knowledge base for you again. One moment! :books:
----------------------
Thank you for pointing out the issue. Based on the knowledge sources provided, there is no explicit mention in the official Nuxt or Nitro documentation that the
afterResponse
hook is skipped when an error is thrown in a server API route using createError
. The documentation states that afterResponse
is "called after sending the response," but does not clarify behavior in the case of errors or exceptions — including those thrown with createError
Docs: Nitro App Hooks (runtime, server-side).
Therefore, the knowledge sources do not contain enough information to confirm or deny the behavior described in the linked GitHub issue. If the issue you referenced demonstrates that afterResponse
is not executed on error, this is not documented in the official sources above. For the most accurate and up-to-date information, you may need to rely on the issue tracker or test the behavior directly in your application.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@693201794137981049> Kapa.ai is still learning and improving, please let me know how I did by reacting below.