🕵️♂️
Next.js API Routesのreq.bodyの仕様が分からなかったのでコード眺めた
今回は軽い記事です。Next.js API Routes の req.body
って何が返ってくるんでしょう。ドキュメント読んでも、
req.body - An object containing the body parsed by content-type, or null if no body was sent
としか書いてません。こまった。調べてみます。
API Routesのデータは packages/next/server/next-server.ts
の runApi()
あたりで受けてそうです。
そこから処理を受ける apiResolver()
をのぞくと、 bodyParser
というキーワードが目に入ってきたので眺めます。
この parseBody()
を読んでみたら良さそうです。以下に該当箇所の抜粋を貼っておきます。
next/server/api-utils.ts
/**
* Parse incoming message like `json` or `urlencoded`
* @param req request object
*/
export async function parseBody(
req: IncomingMessage,
limit: string | number
): Promise<any> {
let contentType
try {
contentType = parse(req.headers['content-type'] || 'text/plain')
} catch {
contentType = parse('text/plain')
}
const { type, parameters } = contentType
const encoding = parameters.charset || 'utf-8'
let buffer
try {
const getRawBody =
require('next/dist/compiled/raw-body') as typeof import('next/dist/compiled/raw-body')
buffer = await getRawBody(req, { encoding, limit })
} catch (e) {
if (isError(e) && e.type === 'entity.too.large') {
throw new ApiError(413, `Body exceeded ${limit} limit`)
} else {
throw new ApiError(400, 'Invalid body')
}
}
const body = buffer.toString()
if (type === 'application/json' || type === 'application/ld+json') {
return parseJson(body)
} else if (type === 'application/x-www-form-urlencoded') {
const qs = require('querystring')
return qs.decode(body)
} else {
return body
}
}
まとめ
- 基本的には
text/plain
として読み込み- bufferは
config.api.bodyParser.sizeLimit
で指定した値か、デフォルトの1mb
- charsetは基本的に
utf-8
だが、Content-Type
に指定されたcharset
があればそれで読み込む
- bufferは
-
Content-Type
がapplication/json
かapplication/ld+json
の場合-
JSON.parse()
で読み込み
-
-
Content-Type
がapplication/x-www-form-urlencoded
の場合-
querystring
パッケージのquerystring.decode()
で読み込み
-
Discussion