检测客户端何时中止
¥Detecting When Clients Abort
介绍
¥Introduction
Fastify 提供了在请求生命周期中的某些点触发的请求事件。但是,没有内置机制来检测客户端意外断开连接的情况,例如客户端的 Internet 连接中断时。本指南介绍了检测客户端是否以及何时故意中止请求的方法。
¥Fastify provides request events to trigger at certain points in a request's lifecycle. However, there isn't a built-in mechanism to detect unintentional client disconnection scenarios such as when the client's internet connection is interrupted. This guide covers methods to detect if and when a client intentionally aborts a request.
请记住,Fastify 的 clientErrorHandler
并非设计用于检测客户端何时中止请求。它的工作方式与标准 Node HTTP 模块相同,当出现错误请求或标头数据过大时,它会触发 clientError
事件。当客户端中止请求时,套接字上没有错误,clientErrorHandler
不会被触发。
¥Keep in mind, Fastify's clientErrorHandler
is not designed to detect when a
client aborts a request. This works in the same way as the standard Node HTTP
module, which triggers the clientError
event when there is a bad request or
exceedingly large header data. When a client aborts a request, there is no
error on the socket and the clientErrorHandler
will not be triggered.
解决方案
¥Solution
概述
¥Overview
所提出的解决方案是一种检测客户端何时故意中止请求的可能方法,例如何时关闭浏览器或何时从客户端应用中止 HTTP 请求。如果你的应用代码中存在导致服务器崩溃的错误,你可能需要额外的逻辑来避免错误的中止检测。
¥The proposed solution is a possible way of detecting when a client intentionally aborts a request, such as when a browser is closed or the HTTP request is aborted from your client application. If there is an error in your application code that results in the server crashing, you may require additional logic to avoid a false abort detection.
这里的目标是检测客户端何时故意中止连接 ,以便你的应用逻辑可以相应地继续进行。这对于日志记录或停止业务逻辑很有用。
¥The goal here is to detect when a client intentionally aborts a connection so your application logic can proceed accordingly. This can be useful for logging purposes or halting business logic.
实际操作
¥Hands-on
假设我们设置了以下基础服务器:
¥Say we have the following base server set up:
import Fastify from 'fastify';
const sleep = async (time) => {
return await new Promise(resolve => setTimeout(resolve, time || 1000));
}
const app = Fastify({
logger: {
transport: {
target: 'pino-pretty',
options: {
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname',
},
},
},
})
app.addHook('onRequest', async (request, reply) => {
request.raw.on('close', () => {
if (request.raw.aborted) {
app.log.info('request closed')
}
})
})
app.get('/', async (request, reply) => {
await sleep(3000)
reply.code(200).send({ ok: true })
})
const start = async () => {
try {
await app.listen({ port: 3000 })
} catch (err) {
app.log.error(err)
process.exit(1)
}
}
start()
我们的代码正在设置一个 Fastify 服务器,其中包括以下功能:
¥Our code is setting up a Fastify server which includes the following functionality:
-
在 http://localhost:3000 接受请求,
{ ok: true }
的响应延迟 3 秒。¥Accepting requests at http://localhost:3000, with a 3 second delayed response of
{ ok: true }
. -
收到每个请求时触发的 onRequest 钩子。
¥An onRequest hook that triggers when every request is received.
-
请求关闭时在钩子中触发的逻辑。
¥Logic that triggers in the hook when the request is closed.
-
当关闭的请求属性
aborted
为真时发生的日志记录。¥Logging that occurs when the closed request property
aborted
is true.
虽然 aborted
属性已被弃用,但 destroyed
并不是 Node.js 文档建议 的合适替代品。请求可以由于各种原因成为 destroyed
,例如当服务器关闭连接时。aborted
属性仍然是检测客户端何时故意中止请求的最可靠方法。
¥Whilst the aborted
property has been deprecated, destroyed
is not a
suitable replacement as the
Node.js documentation suggests.
A request can be destroyed
for various reasons, such as when the server closes
the connection. The aborted
property is still the most reliable way to detect
when a client intentionally aborts a request.