响应
响应
¥Reply
介绍
¥Introduction
处理程序函数的第二个参数是 Reply
。Reply 是 Fastify 的核心对象,它公开以下函数和属性:
¥The second parameter of the handler function is Reply
. Reply is a core Fastify
object that exposes the following functions and properties:
.code(statusCode)
- 设置状态代码。¥
.code(statusCode)
- Sets the status code..status(statusCode)
-.code(statusCode)
的别名。¥
.status(statusCode)
- An alias for.code(statusCode)
..statusCode
- 阅读并设置 HTTP 状态代码。¥
.statusCode
- Read and set the HTTP status code..elapsedTime
- 返回自 Fastify 收到请求以来经过的时间。¥
.elapsedTime
- Returns the amount of time passed since the request was received by Fastify..server
- 对 fastify 实例对象的引用。¥
.server
- A reference to the fastify instance object..header(name, value)
- 设置响应标头。¥
.header(name, value)
- Sets a response header..headers(object)
- 将对象的所有键设置为响应标头。¥
.headers(object)
- Sets all the keys of the object as response headers..getHeader(name)
- 检索已设置的标头的值。¥
.getHeader(name)
- Retrieve value of already set header..getHeaders()
- 获取所有当前响应标头的浅拷贝。¥
.getHeaders()
- Gets a shallow copy of all current response headers..removeHeader(key)
- 删除先前设置的标头的值。¥
.removeHeader(key)
- Remove the value of a previously set header..hasHeader(name)
- 确定是否已设置标头。¥
.hasHeader(name)
- Determine if a header has been set..writeEarlyHints(hints, callback)
- 在准备响应时向用户发送早期提示。¥
.writeEarlyHints(hints, callback)
- Sends early hints to the user while the response is being prepared..trailer(key, function)
- 设置响应预告片。¥
.trailer(key, function)
- Sets a response trailer..hasTrailer(key)
- 确定是否已设置尾部。¥
.hasTrailer(key)
- Determine if a trailer has been set..removeTrailer(key)
- 删除先前设置的预告片的值。¥
.removeTrailer(key)
- Remove the value of a previously set trailer..type(value)
- 设置标头Content-Type
。¥
.type(value)
- Sets the headerContent-Type
..redirect(dest, [code,])
- 重定向到指定的 URL,状态代码是可选的(默认为302
)。¥
.redirect(dest, [code,])
- Redirect to the specified URL, the status code is optional (defaults to302
)..callNotFound()
- 调用自定义未找到处理程序。¥
.callNotFound()
- Invokes the custom not found handler..serialize(payload)
- 使用默认的 JSON 序列化器或使用自定义序列化器(如果已设置)序列化指定的有效负载并返回序列化的有效负载。¥
.serialize(payload)
- Serializes the specified payload using the default JSON serializer or using the custom serializer (if one is set) and returns the serialized payload..getSerializationFunction(schema | httpStatus, [contentType])
- 如果设置了其中任何一个,则返回指定模式或 http 状态的序列化函数。¥
.getSerializationFunction(schema | httpStatus, [contentType])
- Returns the serialization function for the specified schema or http status, if any of either are set..compileSerializationSchema(schema, [httpStatus], [contentType])
- 使用默认(或自定义)SerializerCompiler
编译指定的模式并返回序列化函数。如果提供可选httpStatus
,则转发到SerializerCompiler
,默认为undefined
。¥
.compileSerializationSchema(schema, [httpStatus], [contentType])
- Compiles the specified schema and returns a serialization function using the default (or customized)SerializerCompiler
. The optionalhttpStatus
is forwarded to theSerializerCompiler
if provided, default toundefined
..serializeInput(data, schema, [,httpStatus], [contentType])
- 使用指定的模式序列化指定的数据并返回序列化的有效负载。如果提供了可选的httpStatus
和contentType
,则该函数将使用为该特定内容类型和 HTTP 状态代码提供的序列化器函数。默认为undefined
。¥
.serializeInput(data, schema, [,httpStatus], [contentType])
- Serializes the specified data using the specified schema and returns the serialized payload. If the optionalhttpStatus
, andcontentType
are provided, the function will use the serializer function given for that specific content type and HTTP Status Code. Default toundefined
..serializer(function)
- 为有效负载设置自定义序列化器。¥
.serializer(function)
- Sets a custom serializer for the payload..send(payload)
- 将有效负载发送给用户,可以是纯文本、缓冲区、JSON、流或错误对象。¥
.send(payload)
- Sends the payload to the user, could be a plain text, a buffer, JSON, stream, or an Error object..sent
- 如果你需要知道send
是否已被调用,可以使用布尔值。¥
.sent
- A boolean value that you can use if you need to know ifsend
has already been called..hijack()
- 中断正常请求生命周期。¥
.hijack()
- interrupt the normal request lifecycle..raw
- 来自 Node 核心的http.ServerResponse
。¥
.raw
- Thehttp.ServerResponse
from Node core..log
- 传入请求的日志器实例。¥
.log
- The logger instance of the incoming request..request
- 传入请求。¥
.request
- The incoming request.
fastify.get('/', options, function (request, reply) {
// Your code
reply
.code(200)
.header('Content-Type', 'application/json; charset=utf-8')
.send({ hello: 'world' })
})
.code(statusCode)
如果没有通过 reply.code
设置,则生成的 statusCode
将是 200
。
¥If not set via reply.code
, the resulting statusCode
will be 200
.
.elapsedTime
调用自定义响应时间 getter 来计算自 Fastify 收到请求以来经过的时间。
¥Invokes the custom response time getter to calculate the amount of time passed since the request was received by Fastify.
const milliseconds = reply.elapsedTime
.statusCode
该属性读取并设置 HTTP 状态代码。当用作 setter 时,它是 reply.code()
的别名。
¥This property reads and sets the HTTP status code. It is an alias for
reply.code()
when used as a setter.
if (reply.statusCode >= 299) {
reply.statusCode = 500
}
.server
Fastify 服务器实例,作用域为当前 封装上下文。
¥The Fastify server instance, scoped to the current encapsulation context.
fastify.decorate('util', function util () {
return 'foo'
})
fastify.get('/', async function (req, rep) {
return rep.server.util() // foo
})
.header(key, value)
设置响应标头。如果省略或未定义该值,则将其强制转换为 ''
。
¥Sets a response header. If the value is omitted or undefined, it is coerced to
''
.
注意:标头的值必须使用
encodeURI
或类似模块(如encodeurl
)正确编码。无效字符将导致 500TypeError
响应。¥Note: the header's value must be properly encoded using
encodeURI
or similar modules such asencodeurl
. Invalid characters will result in a 500TypeError
response.
有关更多信息,请参阅 http.ServerResponse#setHeader
。
¥For more information, see
http.ServerResponse#setHeader
.
set-cookie
当以
set-cookie
为键将不同的值作为 cookie 发送时,每个值都将作为 cookie 发送,而不是替换以前的值。¥When sending different values as a cookie with
set-cookie
as the key, every value will be sent as a cookie instead of replacing the previous value.
reply.header('set-cookie', 'foo');
reply.header('set-cookie', 'bar');浏览器将仅考虑
set-cookie
标头的键的最新引用。这样做是为了避免在添加到回复时解析set-cookie
标头并加快回复的序列化速度。¥The browser will only consider the latest reference of a key for the
set-cookie
header. This is done to avoid parsing theset-cookie
header when added to a reply and speeds up the serialization of the reply.要重置
set-cookie
标头,你需要明确调用reply.removeHeader('set-cookie')
,请阅读有关.removeHeader(key)
此处 的更多信息。¥To reset the
set-cookie
header, you need to make an explicit call toreply.removeHeader('set-cookie')
, read more about.removeHeader(key)
here.
.headers(object)
将对象的所有键设置为响应标头。.header
将在后台调用。
¥Sets all the keys of the object as response headers.
.header
will be called under the hood.
reply.headers({
'x-foo': 'foo',
'x-bar': 'bar'
})
.getHeader(key)
检索先前设置的标头的值。
¥Retrieves the value of a previously set header.
reply.header('x-foo', 'foo') // setHeader: key, value
reply.getHeader('x-foo') // 'foo'
.getHeaders()
获取所有当前响应标头的浅拷贝,包括通过原始 http.ServerResponse
设置的响应标头。请注意,通过 Fastify 设置的标头优先于通过 http.ServerResponse
设置的标头。
¥Gets a shallow copy of all current response headers, including those set via the
raw http.ServerResponse
. Note that headers set via Fastify take precedence
over those set via http.ServerResponse
.
reply.header('x-foo', 'foo')
reply.header('x-bar', 'bar')
reply.raw.setHeader('x-foo', 'foo2')
reply.getHeaders() // { 'x-foo': 'foo', 'x-bar': 'bar' }
.removeHeader(key)
删除先前设置的标头的值。
¥Remove the value of a previously set header.
reply.header('x-foo', 'foo')
reply.removeHeader('x-foo')
reply.getHeader('x-foo') // undefined
.hasHeader(key)
返回一个布尔值,指示是否已设置指定的标头。
¥Returns a boolean indicating if the specified header has been set.
.writeEarlyHints(hints, callback)
向客户端发送早期提示。早期提示允许客户端在发送最终响应之前开始处理资源。这可以通过允许客户端在服务器仍在生成响应时预加载或预连接到资源来提高性能。
¥Sends early hints to the client. Early hints allow the client to start processing resources before the final response is sent. This can improve performance by allowing the client to preload or preconnect to resources while the server is still generating the response.
hints 参数是一个包含早期提示键值对的对象。
¥The hints parameter is an object containing the early hint key-value pairs.
示例:
¥Example:
reply.writeEarlyHints({
Link: '</styles.css>; rel=preload; as=style'
});
可选回调参数是一个函数,一旦发送提示或发生错误,该函数将被调用。
¥The optional callback parameter is a function that will be called once the hint is sent or if an error occurs.
.trailer(key, function)
设置响应预告片。通常在你需要在 data
之后发送需要大量资源的标头时使用尾部,例如 Server-Timing
和 Etag
。它可以保证客户端尽快收到响应数据。
¥Sets a response trailer. Trailer is usually used when you need a header that
requires heavy resources to be sent after the data
, for example,
Server-Timing
and Etag
. It can ensure the client receives the response data
as soon as possible.
注意:一旦你使用尾部,就会添加标头 Transfer-Encoding: chunked
。这是在 Node.js 中使用预告片的硬性要求。
¥Note: The header Transfer-Encoding: chunked
will be added once you use the
trailer. It is a hard requirement for using trailer in Node.js.
注意:传递给 done
回调的任何错误都将被忽略。如果你对错误感兴趣,可以打开 debug
级别日志记录。
¥Note: Any error passed to done
callback will be ignored. If you interested
in the error, you can turn on debug
level logging.
reply.trailer('server-timing', function() {
return 'db;dur=53, app;dur=47.2'
})
const { createHash } = require('node:crypto')
// trailer function also receive two argument
// @param {object} reply fastify reply
// @param {string|Buffer|null} payload payload that already sent, note that it will be null when stream is sent
// @param {function} done callback to set trailer value
reply.trailer('content-md5', function(reply, payload, done) {
const hash = createHash('md5')
hash.update(payload)
done(null, hash.disgest('hex'))
})
// when you prefer async-await
reply.trailer('content-md5', async function(reply, payload) {
const hash = createHash('md5')
hash.update(payload)
return hash.disgest('hex')
})
.hasTrailer(key)
返回一个布尔值,指示是否已设置指定的预告片。
¥Returns a boolean indicating if the specified trailer has been set.
.removeTrailer(key)
删除先前设置的预告片的值。
¥Remove the value of a previously set trailer.
reply.trailer('server-timing', function() {
return 'db;dur=53, app;dur=47.2'
})
reply.removeTrailer('server-timing')
reply.getTrailer('server-timing') // undefined
.redirect(dest, [code ,])
将请求重定向到指定的 URL,状态代码是可选的,默认为 302
(如果尚未通过调用 code
设置状态代码)。
¥Redirects a request to the specified URL, the status code is optional, default
to 302
(if status code is not already set by calling code
).
注意:输入的 URL 必须使用
encodeURI
或类似模块(如encodeurl
)进行正确编码。无效的 URL 将导致 500TypeError
响应。¥Note: the input URL must be properly encoded using
encodeURI
or similar modules such asencodeurl
. Invalid URLs will result in a 500TypeError
response.
示例(无 reply.code()
调用)将状态代码设置为 302
并重定向到 /home
¥Example (no reply.code()
call) sets status code to 302
and redirects to
/home
reply.redirect('/home')
示例(无 reply.code()
调用)将状态代码设置为 303
并重定向到 /home
¥Example (no reply.code()
call) sets status code to 303
and redirects to
/home
reply.redirect('/home', 303)
示例(reply.code()
调用)将状态代码设置为 303
并重定向到 /home
¥Example (reply.code()
call) sets status code to 303
and redirects to /home
reply.code(303).redirect('/home')
示例(reply.code()
调用)将状态代码设置为 302
并重定向到 /home
¥Example (reply.code()
call) sets status code to 302
and redirects to /home
reply.code(303).redirect('/home', 302)
.callNotFound()
调用自定义未找到处理程序。请注意,它只会调用 setNotFoundHandler
中指定的 preHandler
钩子。
¥Invokes the custom not found handler. Note that it will only call preHandler
hook specified in setNotFoundHandler
.
reply.callNotFound()
.type(contentType)
设置响应的内容类型。这是 reply.header('Content-Type', 'the/type')
的快捷方式。
¥Sets the content type for the response. This is a shortcut for
reply.header('Content-Type', 'the/type')
.
reply.type('text/html')
如果 Content-Type
具有 JSON 子类型,并且未设置 charset 参数,则默认使用 utf-8
作为字符集。
¥If the Content-Type
has a JSON subtype, and the charset parameter is not set,
utf-8
will be used as the charset by default.
.getSerializationFunction(schema | httpStatus, [contentType])
通过使用提供的 schema
或 httpStatus
以及可选的 contentType
调用此函数,它将返回一个可用于序列化不同输入的 serialzation
函数。如果使用提供的输入中的任何一个都找不到序列化函数,则返回 undefined
。
¥By calling this function using a provided schema
or httpStatus
,
and the optional contentType
, it will return a serialzation
function
that can be used to serialize diverse inputs. It returns undefined
if no
serialization function was found using either of the provided inputs.
这在很大程度上取决于附加到路由的 schema#responses
,或使用 compileSerializationSchema
编译的序列化函数。
¥This heavily depends of the schema#responses
attached to the route, or
the serialization functions compiled by using compileSerializationSchema
.
const serialize = reply
.getSerializationFunction({
type: 'object',
properties: {
foo: {
type: 'string'
}
}
})
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
// or
const serialize = reply
.getSerializationFunction(200)
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
// or
const serialize = reply
.getSerializationFunction(200, 'application/json')
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
请参阅 .compileSerializationSchema(schema, [httpStatus], [contentType]) 了解有关如何编译序列化模式的更多信息。
¥See .compileSerializationSchema(schema, [httpStatus], [contentType]) for more information on how to compile serialization schemas.
.compileSerializationSchema(schema, [httpStatus], [contentType])
该函数将编译序列化模式并返回可用于序列化数据的函数。返回的函数(又名序列化函数)是使用提供的 SerializerCompiler
编译的。此外,使用 WeakMap
可以缓存它以减少编译调用。
¥This function will compile a serialization schema and
return a function that can be used to serialize data.
The function returned (a.k.a. serialization function) returned is compiled
by using the provided SerializerCompiler
. Also this is cached by using
a WeakMap
for reducing compilation calls.
如果提供可选参数 httpStatus
和 contentType
,则直接转发到 SerializerCompiler
,因此如果使用自定义 SerializerCompiler
,则可以使用它来编译序列化函数。
¥The optional parameters httpStatus
and contentType
, if provided,
are forwarded directly to the SerializerCompiler
, so it can be used
to compile the serialization function if a custom SerializerCompiler
is used.
这在很大程度上取决于附加到路由的 schema#responses
,或使用 compileSerializationSchema
编译的序列化函数。
¥This heavily depends of the schema#responses
attached to the route, or
the serialization functions compiled by using compileSerializationSchema
.
const serialize = reply
.compileSerializationSchema({
type: 'object',
properties: {
foo: {
type: 'string'
}
}
})
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
// or
const serialize = reply
.compileSerializationSchema({
type: 'object',
properties: {
foo: {
type: 'string'
}
}
}, 200)
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
// or
const serialize = reply
.compileSerializationSchema({
'3xx': {
content: {
'application/json': {
schema: {
name: { type: 'string' },
phone: { type: 'number' }
}
}
}
}
}, '3xx', 'application/json')
serialize({ name: 'Jone', phone: 201090909090 }) // '{"name":"Jone", "phone":201090909090}'
请注意,使用此函数时应小心,因为它将根据提供的架构缓存已编译的序列化函数。如果提供的模式发生修改或更改,则序列化函数将不会检测到模式已更改,例如,它将根据先前提供的模式的引用重用先前编译的序列化函数。
¥Note that you should be careful when using this function, as it will cache the compiled serialization functions based on the schema provided. If the schemas provided is mutated or changed, the serialization functions will not detect that the schema has been altered and for instance it will reuse the previously compiled serialization function based on the reference of the schema previously provided.
如果需要更改模式的属性,请始终选择创建一个全新的对象,否则实现将无法从缓存机制中受益。
¥If there's a need to change the properties of a schema, always opt to create a totally new object, otherwise the implementation won't benefit from the cache mechanism.
:使用以下模式作为示例:
¥:Using the following schema as example:
const schema1 = {
type: 'object',
properties: {
foo: {
type: 'string'
}
}
}
不是
¥Not
const serialize = reply.compileSerializationSchema(schema1)
// Later on...
schema1.properties.foo.type. = 'integer'
const newSerialize = reply.compileSerializationSchema(schema1)
console.log(newSerialize === serialize) // true
反而
¥Instead
const serialize = reply.compileSerializationSchema(schema1)
// Later on...
const newSchema = Object.assign({}, schema1)
newSchema.properties.foo.type = 'integer'
const newSerialize = reply.compileSerializationSchema(newSchema)
console.log(newSerialize === serialize) // false
.serializeInput(data, [schema | httpStatus], [httpStatus], [contentType])
此函数将根据提供的架构或 HTTP 状态代码序列化输入数据。如果同时提供,则 httpStatus
将优先。
¥This function will serialize the input data based on the provided schema
or HTTP status code. If both are provided the httpStatus
will take precedence.
如果给定的 schema
没有序列化函数,则将编译一个新的序列化函数,如果提供则转发 httpStatus
和 contentType
。
¥If there is not a serialization function for a given schema
a new serialization
function will be compiled, forwarding the httpStatus
and contentType
if provided.
reply
.serializeInput({ foo: 'bar'}, {
type: 'object',
properties: {
foo: {
type: 'string'
}
}
}) // '{"foo":"bar"}'
// or
reply
.serializeInput({ foo: 'bar'}, {
type: 'object',
properties: {
foo: {
type: 'string'
}
}
}, 200) // '{"foo":"bar"}'
// or
reply
.serializeInput({ foo: 'bar'}, 200) // '{"foo":"bar"}'
// or
reply
.serializeInput({ name: 'Jone', age: 18 }, '200', 'application/vnd.v1+json') // '{"name": "Jone", "age": 18}'
请参阅 .compileSerializationSchema(schema, [httpStatus], [contentType]) 了解有关如何编译序列化模式的更多信息。
¥See .compileSerializationSchema(schema, [httpStatus], [contentType]) for more information on how to compile serialization schemas.
.serializer(func)
默认情况下,.send()
将 JSON 序列化任何不属于 Buffer
、stream
、string
、undefined
或 Error
的值。如果你需要将默认序列化器替换为特定请求的自定义序列化器,则可以使用 .serializer()
实用程序执行此操作。请注意,如果你使用自定义序列化器,则必须设置自定义 'Content-Type'
标头。
¥By default, .send()
will JSON-serialize any value that is not one of Buffer
,
stream
, string
, undefined
, or Error
. If you need to replace the default
serializer with a custom serializer for a particular request, you can do so with
the .serializer()
utility. Be aware that if you are using a custom serializer,
you must set a custom 'Content-Type'
header.
reply
.header('Content-Type', 'application/x-protobuf')
.serializer(protoBuf.serialize)
请注意,你不需要在 handler
中使用此实用程序,因为缓冲区、流和字符串(除非设置了序列化程序)被视为已序列化。
¥Note that you don't need to use this utility inside a handler
because Buffers,
streams, and strings (unless a serializer is set) are considered to already be
serialized.
reply
.header('Content-Type', 'application/x-protobuf')
.send(protoBuf.serialize(data))
有关发送不同类型值的更多信息,请参阅 .send()
。
¥See .send()
for more information on sending different types of
values.
.raw
这是来自 Node 核心的 http.ServerResponse
。当你使用 Fastify Reply
对象时,使用 Reply.raw
函数的风险由你自行承担,因为你跳过了处理 HTTP 响应的所有 Fastify 逻辑。例如。:
¥This is the
http.ServerResponse
from Node core. Whilst you are using the Fastify Reply
object, the use of
Reply.raw
functions is at your own risk as you are skipping all the Fastify
logic of handling the HTTP response. e.g.:
app.get('/cookie-2', (req, reply) => {
reply.setCookie('session', 'value', { secure: false }) // this will not be used
// in this case we are using only the nodejs http server response object
reply.raw.writeHead(200, { 'Content-Type': 'text/plain' })
reply.raw.write('ok')
reply.raw.end()
})
响应 中解释了滥用 Reply.raw
的另一个例子。
¥Another example of the misuse of Reply.raw
is explained in
Reply.
.sent
顾名思义,.sent
是一个属性,用于指示是否已通过 reply.send()
发送响应。如果使用 reply.hijack()
,它也将是 true
。
¥As the name suggests, .sent
is a property to indicate if a response has been
sent via reply.send()
. It will also be true
in case reply.hijack()
was
used.
如果路由处理程序被定义为异步函数或它返回 promise,则可以调用 reply.hijack()
来指示应跳过处理程序 promise 解析后自动调用 reply.send()
。通过调用 reply.hijack()
,应用对底层请求和响应承担全部责任。而且,钩子不会被调用。
¥In case a route handler is defined as an async function or it returns a promise,
it is possible to call reply.hijack()
to indicate that the automatic
invocation of reply.send()
once the handler promise resolve should be skipped.
By calling reply.hijack()
, an application claims full responsibility for the
low-level request and response. Moreover, hooks will not be invoked.
直接修改 .sent
属性已被弃用。请使用上述 .hijack()
方法实现相同效果。
¥Modifying the .sent
property directly is deprecated. Please use the
aforementioned .hijack()
method to achieve the same effect.
.hijack()
有时你可能需要停止正常请求生命周期的执行并手动发送响应。
¥Sometimes you might need to halt the execution of the normal request lifecycle and handle sending the response manually.
为了实现这一点,Fastify 提供了可以在请求生命周期内调用的 reply.hijack()
方法(在调用 reply.send()
之前的任何时间点),并允许你阻止 Fastify 发送响应,并阻止运行剩余的钩子(如果回复之前被劫持,则阻止用户处理程序)。
¥To achieve this, Fastify provides the reply.hijack()
method that can be called
during the request lifecycle (At any point before reply.send()
is called), and
allows you to prevent Fastify from sending the response, and from running the
remaining hooks (and user handler if the reply was hijacked before).
app.get('/', (req, reply) => {
reply.hijack()
reply.raw.end('hello world')
return Promise.resolve('this will be skipped')
})
如果使用 reply.raw
将响应发送回用户,则仍将执行 onResponse
钩子。
¥If reply.raw
is used to send a response back to the user, the onResponse
hooks will still be executed.
.send(data)
顾名思义,.send()
是将有效负载发送给终端用户的函数。
¥As the name suggests, .send()
is the function that sends the payload to the
end user.
Objects
如上所述,如果你发送 JSON 对象,如果你设置了输出架构,send
将使用 fast-json-stringify 序列化对象,否则将使用 JSON.stringify()
。
¥As noted above, if you are sending JSON objects, send
will serialize the
object with
fast-json-stringify if you
set an output schema, otherwise, JSON.stringify()
will be used.
fastify.get('/json', options, function (request, reply) {
reply.send({ hello: 'world' })
})
Strings
如果你将字符串传递给没有 Content-Type
的 send
,它将作为 text/plain; charset=utf-8
发送。如果你设置了 Content-Type
标头并将字符串传递给 send
,它将使用自定义序列化器进行序列化(如果已设置),否则,它将被不加修改地发送(除非 Content-Type
标头设置为 application/json; charset=utf-8
,在这种情况下它将像对象一样进行 JSON 序列化 - 请参阅上面的部分)。
¥If you pass a string to send
without a Content-Type
, it will be sent as
text/plain; charset=utf-8
. If you set the Content-Type
header and pass a
string to send
, it will be serialized with the custom serializer if one is
set, otherwise, it will be sent unmodified (unless the Content-Type
header is
set to application/json; charset=utf-8
, in which case it will be
JSON-serialized like an object — see the section above).
fastify.get('/json', options, function (request, reply) {
reply.send('plain string')
})
Streams
如果你正在发送流并且你没有设置 'Content-Type'
标头,send 会将其设置为 'application/octet-stream'
。
¥If you are sending a stream and you have not set a 'Content-Type'
header,
send will set it to 'application/octet-stream'
.
如上所述,流被认为是预序列化的,因此它们将在没有响应验证的情况下未经修改地发送。
¥As noted above, streams are considered to be pre-serialized, so they will be sent unmodified without response validation.
const fs = require('node:fs')
fastify.get('/streams', function (request, reply) {
const stream = fs.createReadStream('some-file', 'utf8')
reply.header('Content-Type', 'application/octet-stream')
reply.send(stream)
})
使用 async-await 时,你需要返回或等待响应对象:
¥When using async-await you will need to return or await the reply object:
const fs = require('node:fs')
fastify.get('/streams', async function (request, reply) {
const stream = fs.createReadStream('some-file', 'utf8')
reply.header('Content-Type', 'application/octet-stream')
return reply.send(stream)
})
Buffers
如果你正在发送缓冲区并且你没有设置 'Content-Type'
标头,send 会将其设置为 'application/octet-stream'
。
¥If you are sending a buffer and you have not set a 'Content-Type'
header,
send will set it to 'application/octet-stream'
.
如上所述,缓冲区被认为是预序列化的,因此它们将在没有响应验证的情况下未经修改地发送。
¥As noted above, Buffers are considered to be pre-serialized, so they will be sent unmodified without response validation.
const fs = require('node:fs')
fastify.get('/streams', function (request, reply) {
fs.readFile('some-file', (err, fileBuffer) => {
reply.send(err || fileBuffer)
})
})
使用 async-await 时,你需要返回或等待响应对象:
¥When using async-await you will need to return or await the reply object:
const fs = require('node:fs')
fastify.get('/streams', async function (request, reply) {
fs.readFile('some-file', (err, fileBuffer) => {
reply.send(err || fileBuffer)
})
return reply
})
TypedArrays
send
像缓冲区一样管理 TypedArray,如果尚未设置,则将 'Content-Type'
标头设置为 'application/octet-stream'
。
¥send
manages TypedArray like a Buffer, and sets the 'Content-Type'
header to 'application/octet-stream'
if not already set.
如上所述,TypedArray/Buffers 被认为是预序列化的,因此它们将在不进行响应验证的情况下未经修改地发送。
¥As noted above, TypedArray/Buffers are considered to be pre-serialized, so they will be sent unmodified without response validation.
const fs = require('node:fs')
fastify.get('/streams', function (request, reply) {
const typedArray = new Uint16Array(10)
reply.send(typedArray)
})
ReadableStream
ReadableStream
将被视为上面提到的节点流,内容被视为预序列化,因此它们将在未经修改的情况下发送,而无需响应验证。
¥ReadableStream
will be treated as a node stream mentioned above,
the content is considered to be pre-serialized, so they will be
sent unmodified without response validation.
const fs = require('node:fs')
const { ReadableStream } = require('node:stream/web')
fastify.get('/streams', function (request, reply) {
const stream = fs.createReadStream('some-file')
reply.header('Content-Type', 'application/octet-stream')
reply.send(ReadableStream.from(stream))
})
响应
¥Response
Response
允许在一个地方管理回复负载、状态代码和标头。Response
中提供的有效负载被视为预序列化,因此它们将在未经修改的情况下发送,而无需进行响应验证。
¥Response
allows to manage the reply payload, status code and
headers in one place. The payload provided inside Response
is
considered to be pre-serialized, so they will be sent unmodified
without response validation.
请注意,使用 Response
时,状态代码和标头不会直接反映到 reply.statusCode
和 reply.getHeaders()
。这种行为基于 Response
仅允许 readonly
状态代码和标头。数据不允许双向编辑,在检查 onSend
钩子中的 payload
时可能会造成混淆。
¥Please be aware when using Response
, the status code and headers
will not directly reflect to reply.statusCode
and reply.getHeaders()
.
Such behavior is based on Response
only allow readonly
status
code and headers. The data is not allow to be bi-direction editing,
and may confuse when checking the payload
in onSend
hooks.
const fs = require('node:fs')
const { ReadableStream } = require('node:stream/web')
fastify.get('/streams', function (request, reply) {
const stream = fs.createReadStream('some-file')
const readableStream = ReadableStream.from(stream)
const response = new Response(readableStream, {
status: 200,
headers: { 'content-type': 'application/octet-stream' }
})
reply.send(response)
})
错误
¥Errors
如果你传递发送一个 Error 实例的对象,Fastify 将自动创建一个结构如下的错误:
¥If you pass to send an object that is an instance of Error, Fastify will automatically create an error structured as the following:
{
error: String // the HTTP error message
code: String // the Fastify error code
message: String // the user error message
statusCode: Number // the HTTP status code
}
你可以向 Error 对象添加自定义属性,例如 headers
,这些属性将用于增强 HTTP 响应。
¥You can add custom properties to the Error object, such as headers
, that will
be used to enhance the HTTP response.
注意:如果你将错误传递给 send
并且 statusCode 小于 400,Fastify 会自动将其设置为 500。
¥Note: If you are passing an error to send
and the statusCode is less than
400, Fastify will automatically set it at 500.
提示:你可以使用 http-errors
模块或 @fastify/sensible
插件生成错误来简化错误:
¥Tip: you can simplify errors by using the
http-errors
module or
@fastify/sensible
plugin to
generate errors:
fastify.get('/', function (request, reply) {
reply.send(httpErrors.Gone())
})
要自定义 JSON 错误输出,你可以通过以下方式完成:
¥To customize the JSON error output you can do it by:
为你需要的状态代码设置响应 JSON 模式
¥setting a response JSON schema for the status code you need
将其他属性添加到
Error
实例¥add the additional properties to the
Error
instance
请注意,如果返回的状态代码不在响应架构列表中,则将应用默认行为。
¥Notice that if the returned status code is not in the response schema list, the default behavior will be applied.
fastify.get('/', {
schema: {
response: {
501: {
type: 'object',
properties: {
statusCode: { type: 'number' },
code: { type: 'string' },
error: { type: 'string' },
message: { type: 'string' },
time: { type: 'string' }
}
}
}
}
}, function (request, reply) {
const error = new Error('This endpoint has not been implemented')
error.time = 'it will be implemented in two weeks'
reply.code(501).send(error)
})
如果你想自定义错误处理,请查看 setErrorHandler
API。
¥If you want to customize error handling, check out
setErrorHandler
API.
注意:你在自定义错误处理程序时负责记录日志
¥Note: you are responsible for logging when customizing the error handler
应用编程接口:
¥API:
fastify.setErrorHandler(function (error, request, reply) {
request.log.warn(error)
const statusCode = error.statusCode >= 400 ? error.statusCode : 500
reply
.code(statusCode)
.type('text/plain')
.send(statusCode >= 500 ? 'Internal server error' : error.message)
})
请注意,在自定义错误处理程序中调用 reply.send(error)
会将错误发送到默认错误处理程序。查看 Reply 生命周期 以获取更多信息。
¥Beware that calling reply.send(error)
in your custom error handler will send
the error to the default error handler.
Check out the Reply Lifecycle
for more information.
路由生成的未找到错误将使用 setNotFoundHandler
¥The not found errors generated by the router will use the
setNotFoundHandler
应用编程接口:
¥API:
fastify.setNotFoundHandler(function (request, reply) {
reply
.code(404)
.type('text/plain')
.send('a custom not found')
})
最终有效负载的类型
¥Type of the final payload
发送的有效负载的类型(在序列化并经过任何 onSend
钩子 之后)必须是以下类型之一,否则将引发错误:
¥The type of the sent payload (after serialization and going through any
onSend
hooks) must be one of the following types,
otherwise, an error will be thrown:
string
Buffer
stream
undefined
null
异步等待和 Promise
¥Async-Await and Promises
Fastify 原生处理 Promise 并支持异步等待。
¥Fastify natively handles promises and supports async-await.
请注意,在以下示例中我们没有使用 reply.send。
¥Note that in the following examples we are not using reply.send.
const { promisify } = require('node:util')
const delay = promisify(setTimeout)
fastify.get('/promises', options, function (request, reply) {
return delay(200).then(() => { return { hello: 'world' }})
})
fastify.get('/async-await', options, async function (request, reply) {
await delay(200)
return { hello: 'world' }
})
被拒绝的 promise 默认为 500
HTTP 状态代码。使用具有 statusCode
(或 status
)和 message
属性的对象拒绝 promise 或 async function
中的 throw
以修改回复。
¥Rejected promises default to a 500
HTTP status code. Reject the promise, or
throw
in an async function
, with an object that has statusCode
(or
status
) and message
properties to modify the reply.
fastify.get('/teapot', async function (request, reply) {
const err = new Error()
err.statusCode = 418
err.message = 'short and stout'
throw err
})
fastify.get('/botnet', async function (request, reply) {
throw { statusCode: 418, message: 'short and stout' }
// will return to the client the same json
})
如果你想了解更多信息,请查看 路由#async-await。
¥If you want to know more please review Routes#async-await.
.then(fulfilled, rejected)
顾名思义,可以等待 Reply
对象,即 await reply
将等待直到发送回复。await
语法调用 reply.then()
。
¥As the name suggests, a Reply
object can be awaited upon, i.e. await reply
will wait until the reply is sent. The await
syntax calls the reply.then()
.
reply.then(fulfilled, rejected)
接受两个参数:
¥reply.then(fulfilled, rejected)
accepts two parameters:
响应完全发送后,将调用
fulfilled
,¥
fulfilled
will be called when a response has been fully sent,如果底层流出现错误,例如套接字已被破坏,将调用
rejected
。¥
rejected
will be called if the underlying stream had an error, e.g. the socket has been destroyed.
有关更多详细信息,请参阅:
¥For more details, see:
https://github.com/fastify/fastify/issues/1864 用于讨论此功能
¥https://github.com/fastify/fastify/issues/1864 for the discussion about this feature
https://web.nodejs.cn/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then 用于签名
¥https://web.nodejs.cn/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then for the signature