メインコンテンツにスキップ
バージョン: 最新 (v5.0.x)

ContentTypeParser

Content-Type パーサー

Fastifyはネイティブで'application/json''text/plain'のコンテンツタイプのみをサポートしています。コンテンツタイプがこれらのいずれでもない場合、FST_ERR_CTP_INVALID_MEDIA_TYPEエラーがスローされます。その他の一般的なコンテンツタイプは、プラグインを使用してサポートされます。

デフォルトの文字セットはutf-8です。異なるコンテンツタイプをサポートする必要がある場合は、addContentTypeParser APIを使用できます。 _デフォルトのJSONまたはプレーンテキストパーサーは変更または削除できます。_

注意: Content-Typeヘッダーで独自のコンテンツタイプを指定する場合、UTF-8はデフォルトになりません。text/html; charset=utf-8のようにUTF-8を含めてください。

他のAPIと同様に、addContentTypeParserは宣言されたスコープにカプセル化されます。これは、ルートスコープで宣言するとどこでも使用できますが、プラグイン内で宣言すると、そのスコープとその子でのみ使用できることを意味します。

Fastifyは、解析されたリクエストペイロードをFastifyリクエストオブジェクトに自動的に追加します。これはrequest.bodyでアクセスできます。

GETおよびHEADリクエストの場合、ペイロードは解析されません。 OPTIONSおよびDELETEリクエストの場合、ペイロードはcontent-typeヘッダーでコンテンツタイプが指定されている場合にのみ解析されます。指定されていない場合、POSTPUTPATCHのようにキャッチオールパーサーは実行されず、ペイロードは単に解析されません。

⚠ セキュリティに関する注意

正規表現を使用してContent-Typeを検出する場合、Content-Typeを適切に検出する方法に注意する必要があります。たとえば、application/*が必要な場合は、エッセンスMIMEタイプのみを一致させるために/^application\/([\w-]+);?/を使用する必要があります。

使用方法

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) {
var 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は、一致するRegExpを見つける前に、最初にstring値を持つcontent-typeパーサーとの一致を試みます。重複するコンテンツタイプを提供する場合、Fastifyは、渡された最後のコンテンツタイプから始めて最初のコンテンツタイプで終わることで、一致するコンテンツタイプを見つけようとします。そのため、一般的なコンテンツタイプをより正確に指定する場合は、以下の例のように、最初に一般的なコンテンツタイプを指定してから、より具体的なコンテンツタイプを指定します。

// 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) => {} )

fastify.registerでaddContentTypeParserを使用する

fastify.registerと組み合わせてaddContentTypeParserを使用する場合、ルートを登録するときにawaitを使用しないでください。 awaitを使用すると、ルートの登録が非同期になり、addContentTypeParserが設定される前にルートが登録される可能性があります。

正しい使用方法

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 APIに加えて、さらに使用できるAPIがあります。これらはhasContentTypeParserremoveContentTypeParser、およびremoveAllContentTypeParsersです。

hasContentTypeParser

hasContentTypeParser APIを使用して、特定のコンテンツタイプパーサーが既に存在するかどうかを確認できます。

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コンテンツタイプをサポートしています。

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

すぐ上の例では、削除したい各コンテンツタイプを指定する必要があることに気付くでしょう。この問題を解決するために、FastifyはremoveAllContentTypeParsers APIを提供しています。これは、現在存在するすべてのコンテンツタイプパーサーを削除するために使用できます。以下の例では、削除する各コンテンツタイプを指定する必要がないことを除いて、上記の例と同じことを実現します。 removeContentTypeParserと同様に、このAPIはカプセル化をサポートしています。このAPIは、すべてのコンテンツタイプに対して実行されるキャッチオールコンテンツタイプパーサーを登録し、組み込みパーサーも無視する場合に特に役立ちます。

fastify.removeAllContentTypeParsers()

fastify.addContentTypeParser('text/xml', function (request, payload, done) {
xmlParser(payload, function (err, body) {
done(err, body)
})
})

**注意**: パーサーの古い構文`function(req, done)`と`async function(req)`はまだサポートされていますが、非推奨です。

ボディパーサー

リクエストの本文は2つの方法で解析できます。1つ目は上記のとおりです。カスタムコンテンツタイプパーサーを追加して、リクエストストリームを処理します。2つ目では、本文を取得する方法を宣言するparseAsオプションをaddContentTypeParser APIに渡す必要があります。これは、'string'または'buffer'タイプのいずれかになります。 parseAsオプションを使用すると、Fastifyは内部でストリームを処理し、本文の最大サイズやコンテンツの長さなど、いくつかのチェックを実行します。制限を超えると、カスタムパーサーは呼び出されません。

fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
try {
var json = JSON.parse(body)
done(null, json)
} catch (err) {
err.statusCode = 400
done(err, undefined)
}
})

例については、example/parser.jsを参照してください。

カスタムパーサーオプション
  • parseAs (文字列): 受信データをどのように収集するかを指定する'string'または'buffer'のいずれか。デフォルト: 'buffer'
  • bodyLimit (数値): カスタムパーサーが受け入れる最大ペイロードサイズ(バイト単位)。デフォルトは、Fastifyファクトリ関数に渡されるグローバルボディ制限です。

キャッチオール

コンテンツタイプに関係なくすべてのリクエストをキャッチする必要がある場合があります。Fastifyでは、'*'コンテンツタイプを使用するだけです。

fastify.addContentTypeParser('*', function (request, payload, done) {
var data = ''
payload.on('data', chunk => { data += chunk })
payload.on('end', () => {
done(null, data)
})
})

これを使用すると、対応するコンテンツタイプパーサーがないすべてのリクエストは、指定された関数によって処理されます。

これは、リクエストストリームをパイプするのにも役立ちます。次のようなコンテンツパーサーを定義できます

fastify.addContentTypeParser('*', function (request, payload, done) {
done()
})

次に、コアHTTPリクエストに直接アクセスして、必要な場所にパイプします

app.post('/hello', (request, reply) => {
reply.send(request.raw)
})

受信json lineオブジェクトをログに記録する完全な例を次に示します

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
}
})

ファイルのアップロードをパイプする場合は、このプラグインを確認してください。

特定のコンテンツタイプがないコンテンツタイプだけでなく、すべてのコンテンツタイプでコンテンツタイプパーサーを実行する場合は、最初にremoveAllContentTypeParsersメソッドを呼び出す必要があります。

// 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) {
var data = ''
payload.on('data', chunk => { data += chunk })
payload.on('end', () => {
done(null, data)
})
})