Content-Type
解析器
Content-Type
解析器
¥Content-Type
Parser
Fastify 原生支持 'application/json'
和 'text/plain'
内容类型,默认字符集为 utf-8
。这些默认解析器可以更改或删除。
¥Fastify natively supports 'application/json'
and 'text/plain'
content types
with a default charset of utf-8
. These default parsers can be changed or
removed.
不支持的内容类型将引发 FST_ERR_CTP_INVALID_MEDIA_TYPE
错误。
¥Unsupported content types will throw an FST_ERR_CTP_INVALID_MEDIA_TYPE
error.
要支持其他内容类型,请使用 addContentTypeParser
API 或现有的 plugin。
¥To support other content types, use the addContentTypeParser
API or an
existing plugin.
与其他 API 一样,addContentTypeParser
封装在声明它的范围中。如果在根作用域中声明,则它在任何地方都可用;如果在插件中声明,则它仅在该范围及其子范围内可用。
¥As with other APIs, addContentTypeParser
is encapsulated in the scope in which
it is declared. If declared in the root scope, it is available everywhere; if
declared in a plugin, it is available only in that scope and its children.
Fastify 会自动将解析后的请求负载添加到 Fastify 请求 对象,可通过 request.body
访问。
¥Fastify automatically adds the parsed request payload to the Fastify
request object, accessible via request.body
.
请注意,对于 GET
和 HEAD
请求,有效负载永远不会被解析。对于 OPTIONS
和 DELETE
请求,仅当提供有效的 content-type
标头时才会解析有效负载。与 POST
、PUT
和 PATCH
不同,catch-all 解析器不会被执行,并且负载不会被解析。
¥Note that for GET
and HEAD
requests, the payload is never parsed. For
OPTIONS
and DELETE
requests, the payload is parsed only if a valid
content-type
header is provided. Unlike POST
, PUT
, and PATCH
, the
catch-all parser is not executed, and the payload is simply not
parsed.
⚠ 警告:使用正则表达式检测
Content-Type
时,确保正确检测非常重要。例如,要匹配application/*
,请使用/^application\/([\w-]+);?/
仅匹配 本质 MIME 类型。¥⚠ Warning: When using regular expressions to detect
Content-Type
, it is important to ensure proper detection. For example, to matchapplication/*
, use/^application\/([\w-]+);?/
to match the essence MIME type only.
用法
¥Usage
fastify.addContentTypeParser('application/jsoff', function (request, payload, done) {
jsoffParser(payload, function (err, body) {
done(err, body)
})
})
// Handle multiple content types with the same function
fastify.addContentTypeParser(['text/xml', 'application/xml'], function (request, payload, done) {
xmlParser(payload, function (err, body) {
done(err, body)
})
})
// Async is also supported in Node versions >= 8.0.0
fastify.addContentTypeParser('application/jsoff', async function (request, payload) {
const res = await jsoffParserAsync(payload)
return res
})
// Handle all content types that matches RegExp
fastify.addContentTypeParser(/^image\/([\w-]+);?/, function (request, payload, done) {
imageParser(payload, function (err, body) {
done(err, body)
})
})
// Can use default JSON/Text parser for different content Types
fastify.addContentTypeParser('text/json', { parseAs: 'string' }, fastify.getDefaultJsonParser('ignore', 'ignore'))
Fastify 首先尝试将内容类型解析器与 string
值匹配,然后再尝试查找匹配的 RegExp
。对于重叠的内容类型,它从配置的最后一个开始,以第一个结束(后进先出)。要更精确地指定一般内容类型,请首先指定一般类型,然后指定特定类型,如下所示。
¥Fastify first tries to match a content-type parser with a string
value before
trying to find a matching RegExp
. For overlapping content types, it starts
with the last one configured and ends with the first (last in, first out).
To specify a general content type more precisely, first specify the general
type, then the specific one, as shown below.
// Here only the second content type parser is called because its value also matches the first one
fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )
fastify.addContentTypeParser('application/vnd.custom', (request, body, done) => {} )
// Here the desired behavior is achieved because fastify first tries to match the
// `application/vnd.custom+xml` content type parser
fastify.addContentTypeParser('application/vnd.custom', (request, body, done) => {} )
fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )
使用 addContentTypeParser 和 fastify.register
¥Using addContentTypeParser with fastify.register
当将 addContentTypeParser
与 fastify.register
一起使用时,注册路由时请避免使用 await
。使用 await
使路由注册异步,可能在设置 addContentTypeParser
之前注册路由。
¥When using addContentTypeParser
with fastify.register
, avoid await
when registering routes. Using await
makes route registration asynchronous,
potentially registering routes before addContentTypeParser
is set.
正确用法
¥Correct Usage
const fastify = require('fastify')();
fastify.register((fastify, opts) => {
fastify.addContentTypeParser('application/json', function (request, payload, done) {
jsonParser(payload, function (err, body) {
done(err, body)
})
})
fastify.get('/hello', async (req, res) => {});
});
除了 addContentTypeParser
,hasContentTypeParser
、removeContentTypeParser
和 removeAllContentTypeParsers
API 也可用。
¥In addition to addContentTypeParser
, the hasContentTypeParser
,
removeContentTypeParser
, and removeAllContentTypeParsers
APIs are available.
hasContentTypeParser
使用 hasContentTypeParser
API 检查是否存在特定内容类型解析器。
¥Use the hasContentTypeParser
API to check if a specific content type parser
exists.
if (!fastify.hasContentTypeParser('application/jsoff')){
fastify.addContentTypeParser('application/jsoff', function (request, payload, done) {
jsoffParser(payload, function (err, body) {
done(err, body)
})
})
}
removeContentTypeParser
removeContentTypeParser
可以删除单个内容类型或内容类型数组,同时支持 string
和 RegExp
。
¥removeContentTypeParser
can remove a single content type or an array of
content types, supporting both string
and RegExp
.
fastify.addContentTypeParser('text/xml', function (request, payload, done) {
xmlParser(payload, function (err, body) {
done(err, body)
})
})
// Removes the both built-in content type parsers so that only the content type parser for text/html is available
fastify.removeContentTypeParser(['application/json', 'text/plain'])
removeAllContentTypeParsers
removeAllContentTypeParsers
API 删除了所有现有的内容类型解析器,无需单独指定每个解析器。此 API 支持封装,可用于注册应该为每种内容类型执行的 包罗万象的内容类型解析器,忽略内置解析器。
¥The removeAllContentTypeParsers
API removes all existing content type parsers
eliminating the need to specify each one individually. This API supports
encapsulation and is useful for registering a
catch-all content type parser that should be executed for every
content type, ignoring built-in parsers.
fastify.removeAllContentTypeParsers()
fastify.addContentTypeParser('text/xml', function (request, payload, done) {
xmlParser(payload, function (err, body) {
done(err, body)
})
})
🛈 注意:
function(req, done)
和async function(req)
仍受支持,但已弃用。¥🛈 Note:
function(req, done)
andasync function(req)
are still supported but deprecated.
正文解析器
¥Body Parser
请求主体可以通过两种方式解析。首先,添加自定义内容类型解析器并处理请求流。或者其次,使用 addContentTypeParser
API 中的 parseAs
选项,指定 'string'
或 'buffer'
。Fastify 将处理流,检查主体的 最大尺寸 和内容长度。如果超出限制,则不会调用自定义解析器。
¥The request body can be parsed in two ways. First, add a custom content type
parser and handle the request stream. Or second, use the parseAs
option in the
addContentTypeParser
API, specifying 'string'
or 'buffer'
. Fastify will
handle the stream, check the maximum size of
the body, and the content length. If the limit is exceeded, the custom parser
will not be invoked.
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
try {
const json = JSON.parse(body)
done(null, json)
} catch (err) {
err.statusCode = 400
done(err, undefined)
}
})
请参阅 example/parser.js
了解示例。
¥See
example/parser.js
for an example.
自定义解析器选项
¥Custom Parser Options
-
parseAs
(字符串):'string'
或'buffer'
指定应如何收集传入数据。默认:'buffer'
。¥
parseAs
(string):'string'
or'buffer'
to designate how the incoming data should be collected. Default:'buffer'
. -
bodyLimit
(数字):自定义解析器将接受的最大有效负载大小(以字节为单位)。默认为传递给Fastify factory function
的全局主体限制。¥
bodyLimit
(number): The maximum payload size, in bytes, that the custom parser will accept. Defaults to the global body limit passed to theFastify factory function
.
Catch-All
要捕获所有请求(无论内容类型如何),请使用 '*'
内容类型:
¥To catch all requests regardless of content type, use the '*'
content type:
fastify.addContentTypeParser('*', function (request, payload, done) {
let data = ''
payload.on('data', chunk => { data += chunk })
payload.on('end', () => {
done(null, data)
})
})
此函数将处理所有没有相应内容类型解析器的请求。
¥All requests without a corresponding content type parser will be handled by this function.
这对于管道请求流也很有用。定义内容解析器,例如:
¥This is also useful for piping the request stream. Define a content parser like:
fastify.addContentTypeParser('*', function (request, payload, done) {
done()
})
然后直接访问核心 HTTP 请求进行管道:
¥And then access the core HTTP request directly for piping:
app.post('/hello', (request, reply) => {
reply.send(request.raw)
})
这是一个记录传入 json 行 对象的完整示例:
¥Here is a complete example that logs incoming json line objects:
const split2 = require('split2')
const pump = require('pump')
fastify.addContentTypeParser('*', (request, payload, done) => {
done(null, pump(payload, split2(JSON.parse)))
})
fastify.route({
method: 'POST',
url: '/api/log/jsons',
handler: (req, res) => {
req.body.on('data', d => console.log(d)) // log every incoming object
}
})
对于管道文件上传,请查看 @fastify/multipart
。
¥For piping file uploads, check out
@fastify/multipart
.
要对所有内容类型执行内容类型解析器,请先调用 removeAllContentTypeParsers
。
¥To execute the content type parser on all content types, call
removeAllContentTypeParsers
first.
// Without this call, the request body with the content type application/json would be processed by the built-in JSON parser
fastify.removeAllContentTypeParsers()
fastify.addContentTypeParser('*', function (request, payload, done) {
const data = ''
payload.on('data', chunk => { data += chunk })
payload.on('end', () => {
done(null, data)
})
})