️ Perpustakaan ini ditulis untuk mendukung rute API yang menggunakan router halaman berikutnya.js. Itu belum diuji dengan router aplikasi.
Rute API Next.js adalah cara yang sangat menyenangkan dan sederhana untuk menambahkan fungsi backend ke aplikasi React. Namun, ketika tiba saatnya untuk menambahkan middleware, tidak ada cara mudah untuk mengimplementasikannya.
Dokumen resmi Next.js merekomendasikan fungsi menulis di dalam penangan rute API Anda. Ini adalah langkah mundur yang besar dibandingkan dengan API bersih yang disediakan oleh Express.js atau Koa.js.
Perpustakaan ini berupaya memberikan pola middleware yang minim, bersih, dan dapat dikomposisikan yang produktif dan menyenangkan untuk digunakan.
labeluse import { label , Middleware } from "next-api-middleware" ;
import * as Sentry from "@sentry/nextjs" ;
import nanoid from "nanoid" ;
// 1 – Create middleware functions
const captureErrors : Middleware = async ( req , res , next ) => {
try {
// Catch any errors that are thrown in remaining
// middleware and the API route handler
await next ( ) ;
} catch ( err ) {
const eventId = Sentry . captureException ( err ) ;
res . status ( 500 ) ;
res . json ( { error : err } ) ;
}
} ;
const addRequestId : Middleware = async ( req , res , next ) => {
// Let remaining middleware and API route execute
await next ( ) ;
// Apply header
res . setHeader ( "X-Response-ID" , nanoid ( ) ) ;
} ;
// 2 – Use `label` to assemble all middleware
const withMiddleware = label (
{
addRequestId ,
sentry : captureErrors , // <-- Optionally alias middleware
} ,
[ "sentry" ] // <-- Provide a list of middleware to call automatically
) ;
// 3 – Define your API route handler
const apiRouteHandler = async ( req , res ) => {
res . status ( 200 ) ;
res . send ( "Hello world!" ) ;
} ;
// 4 – Choose middleware to invoke for this API route
export default withMiddleware ( "addRequestId" ) ( apiRouteHandler ) ; Model mental saya tentang bagaimana perpustakaan ini menangani fungsi middleware adalah "tumpukan belitan dan lepas".
Mari kita bayangkan Anda menggunakan label untuk menambahkan dua fungsi middleware ke rute API.
Ketika sebuah permintaan masuk, ini adalah kesan kasar tentang bagaimana permintaan itu berhasil melalui semua fungsi middleware, penangan rute API itu sendiri, dan kemudian kembali melalui middleware.
|-----------------|-----------------|--------------------|
| Middleware #1 | Middleware #2 | API Route Handler |
|-----------------|-----------------|--------------------|
| | | |
Request ------|----> Setup -----|----> Setup -----|-->------| |
| | | | |
|-----------------|-----------------| V |
| | | |
| await next() | await next() | API stuff |
| | | |
|-----------------|-----------------| | |
| | | | |
Response <----|--- Teardown <---|--- Teardown <---|---------| |
| | | |
|-----------------|-----------------|--------------------|
Meskipun ini adalah diagram ASCII yang payah, saya pikir itu memberi kesan yang tepat. Permintaan berjalan dengan cara meskipun setiap fungsi middleware berturut -turut, mengenai penangan rute API, dan kemudian melanjutkan untuk "melepas" jalannya melalui tumpukan.
Setiap fungsi middleware memiliki kesempatan untuk melewati tiga fase:
Fase "Pengaturan" mencakup semua yang terjadi sebelum await next() . Fase "menunggu" benar -benar await next() . Fase "Teardown" adalah kode yang tersisa dalam fungsi middleware setelah await next() .
Perlu dicatat bahwa meskipun fase -fase ini tersedia untuk semua fungsi middleware, Anda tidak perlu memanfaatkan semuanya.
Misalnya, dalam kesalahan menangkap middleware Anda mungkin cukup membungkus await next() di blok try / catch . Di sisi lain, Anda mungkin memiliki middleware waktu permintaan yang menangkap waktu mulai selama fase pengaturan, menunggu, dan kemudian menangkap waktu selesai dalam fase air mata.
labelIni adalah utilitas utama untuk membuat koleksi middleware yang dapat digunakan kembali untuk digunakan di banyak rute API berikutnya.
const withMiddleware = label ( middleware , defaults ) ; middleware : Objek yang berisi fungsi middleware atau array middlewaredefaults : (opsional) Array tombol middleware yang akan dipanggil secara otomatis label Mengembalikan fungsi (secara konvensional disebut sebagai withMiddleware ) yang menggunakan kari untuk menerima daftar nama middleware yang akan dipanggil, diikuti oleh fungsi penangan API selanjutnya.
Biasanya, withMiddleware akan diimpor dalam file rute API dan digunakan pada pernyataan ekspor default:
import { withMiddleware } from "../helpers/my-middleware" ;
const apiRouteHandler = async ( req , res ) => {
...
}
export default withMiddleware ( "foo" , "bar" , "baz" ) ( apiRouteHandler ) ; Meskipun label dapat berisi banyak fungsi middleware, middleware yang sebenarnya dipanggil oleh rute API ditentukan oleh nama -nama yang diteruskan ke withMiddleware .
const logErrors = async ( req , res , next ) => {
try {
await next ( ) ;
} catch ( error ) {
console . error ( error ) ;
res . status ( 500 ) ;
res . json ( { error } ) ;
}
} ;
const withMiddleware = label ( {
logErrors ,
} ) ;
// export default withMiddleware("logErrors")(apiRouteHandler); const withMiddleware = label ( {
error : logErrors ,
} ) ;
// export default withMiddleware("error")(apiRouteHandler); import { foo , bar , baz } from "./my-middleware" ;
const withMiddleware = label ( {
error : logErrors ,
myGroup : [ foo , bar , baz ] ,
} ) ;
// export default withMiddleware("error", "myGroup")(apiRouteHandler); const withMiddleware = label (
{
error : logErrors ,
myGroup : [ foo , bar , baz ] ,
} ,
[ "error" ]
) ;
// export default withMiddleware("myGroup")(apiRouteHandler);use Utilitas ini menerima fungsi middleware secara langsung dan menjalankan semuanya secara berurutan. Ini adalah alternatif yang lebih sederhana untuk label yang dapat berguna untuk menangani fungsi middleware satu kali.
const withInlineMiddleware = use ( ... middleware ) ; middleware : Daftar fungsi middleware dan/atau array fungsi middleware use pengembalian fungsi yang menerima penangan rute API selanjutnya.js.
import { use } from "next-api-middleware" ;
import cors from "cors" ;
const apiRouteThatOnlyNeedsCORS = async ( req , res ) => {
...
}
export default use ( cors ( ) ) ( apiRouteThatOnlyNeedsCORS ) ; Lihat contoh.md untuk contoh label dan use yang lebih rinci.
Karena use dan label menerima nilai yang mengevaluasi fungsi middleware, ini memberikan kesempatan untuk membuat pabrik middleware khusus.
Berikut adalah contoh pabrik yang menghasilkan fungsi middleware untuk hanya mengizinkan permintaan dengan metode HTTP yang diberikan:
import { Middleware } from "next-api-middleware" ;
const httpMethod = (
allowedHttpMethod : "GET" | "POST" | "PATCH"
) : Middleware => {
return async function ( req , res , next ) {
if ( req . method === allowedHttpMethod || req . method == "OPTIONS" ) {
await next ( ) ;
} else {
res . status ( 404 ) ;
res . end ( ) ;
}
} ;
} ;
export const postRequestsOnlyMiddleware = httpMethod ( "POST" ) ; Middleware terinspirasi oleh gaya middleware asyncronous yang dipopulerkan oleh Koa.js.
type Middleware < Request = NextApiRequest , Response = NextApiResponse > = (
req : Request ,
res : Response ,
next : ( ) => Promise < void >
) => Promise < void > ;