【Next.js和訳】API Routes/API Middlewares
この記事について
この記事は、API Routes/API Middlewaresの記事を和訳したものです。
記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。
API Middlewares
API ルートには、入力されたリクエスト(req
)を解析するミドルウェアが組み込まれています。それらのミドルウェアは
-
req.cookies
- リクエストによって送信された cookies を含むオブジェクトです。デフォルトは{}
です。 -
req.query
- クエリ文字列を含むオブジェクト。デフォルトは{}
です。 -
req.body
-content-type
で解析されたボディを含むオブジェクト、またはボディが送信されていない場合はnull
。
コンフィグのカスタム
すべての API ルートは、デフォルトの設定を変更するために、config
オブジェクトをエクスポートすることができ、その内容は次のとおりです。
export const config = {
api: {
bodyParser: {
sizeLimit: "1mb",
},
},
}
api
オブジェクトは、API ルートで利用可能なすべての設定を含みます。
bodyParser
ボディの解析を有効にします。Stream
として消費したい場合は無効にすることができます。
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
は、解析されたボディに許容される最大サイズで、バイトでサポートされる任意のフォーマットで、以下のようになります。
export const config = {
api: {
bodyParser: {
sizeLimit: "500kb",
},
},
}
externalResolver
は明示的なフラグで、このルートが express や connect などの外部リゾルバで処理されていることをサーバに伝えます。このオプションを有効にすると、未解決のリクエストに対する警告が無効になります。
export const config = {
api: {
externalResolver: true,
},
}
Connect/Express 対応ミドルウェア
Connect互換のミドルウェアを使用することもできます。
例えば、API のエンドポイントにCORS を設定するには、corsパッケージを活用します。
まず、cors
をインストールします。
npm i cors
# or
yarn add cors
それでは、API ルートにcors
を追加してみましょう。
import Cors from "cors"
// corsミドルウェアの初期化
const cors = Cors({
methods: ["GET", "HEAD"],
})
// ミドルウェアが実行されるのを待ってから続行するヘルパーメソッド
// また、ミドルウェアでエラーが発生したときにエラーを出す
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
async function handler(req, res) {
// ミドルウェアの実行
await runMiddleware(req, res, cors)
// 残りのAPIロジック
res.json({ message: "Hello Everyone!" })
}
export default handler
req
/res
オブジェクトの拡張
TypeScript によるtype-safety をよくするために、req
とres
のオブジェクトを拡張することはお勧めしません。代わりに、関数を使ってこれらを操作します。
import { serialize, CookieSerializeOptions } from 'cookie'
import { NextApiResponse } from 'next'
/**
* これは、`res`オブジェクトを使用して`cookie`を設定します。
*/
export const setCookie = (
res: NextApiResponse,
name: string,
value: unknown,
options: CookieSerializeOptions = {}
) => {
const stringValue =
typeof value === 'object' ? 'j:' + JSON.stringify(value) : String(value)
if ('maxAge' in options) {
options.expires = new Date(Date.now() + options.maxAge)
options.maxAge /= 1000
}
res.setHeader('Set-Cookie', serialize(name, String(stringValue), options))
}
import { NextApiRequest, NextApiResponse } from 'next'
import { setCookie } from '../../utils/cookies'
const handler = (req: NextApiRequest, res: NextApiResponse) => {
// `res`オブジェクトを使って純粋な関数を呼び出すと、`set-cookie`ヘッダーが追加されます。
setCookie(res, 'Next.js', 'api-middleware!')
// `set-cookie`ヘッダーを返すので、それをブラウザで表示して、動作することを示すことができます。
res.end(res.getHeader('Set-Cookie'))
}
export default handler
これらのオブジェクトが拡張されるのを避けられない場合は、追加のプロパティを含む独自のタイプを作成する必要があります。
import { NextApiRequest, NextApiResponse } from 'next'
import { withFoo } from 'external-lib-foo'
type NextApiRequestWithFoo = NextApiRequest & {
foo: (bar: string) => void
}
const handler = (req: NextApiRequestWithFoo, res: NextApiResponse) => {
req.foo('bar') // これで `req.foo` をタイプエラーなしで使えるようになりました。
res.end('ok')
}
export default withFoo(handler)
withFoo()
をエクスポートから削除してもコードはコンパイルされてしまうので、これは安全ではないことに注意してください。
Discussion