UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Next.js】next-connectを使ってAPIのミドルウェアを簡単につくる

Next.jsのAPI Routesを使ってAPIサーバーをつくれることを知った uga-box.hatenablog.com

このAPIでのやりとりに際し、認証機能やDBからデータを取得する場合のミドルウェアを考える

このときにnext-connectを使うと簡単につくれそうなので調べてみた www.npmjs.com

公式サンプルも用意されている
https://github.com/vercel/next.js/tree/canary/examples/with-passport-and-next-connect

ディレクトリ構成はこのようにすると良い感じ

/pages
  ├ api/
  │  └ users.js
  ...
/middleware
  └ auth.js

/middleware/auth.js で認証周りを書く

Express のようにuse メソッドを使って追加することができる

import nextConnect from "next-connect";

export default nextConnect()
  .use((req, res, next) => {
    // ミドルウェアの処理を追加する
    - headerのAuthenticationでリクエストの認証をする
    next();
  });

/pages/api/users.js

next-connectを使うと、各HTTPメソッドに対する処理が if文やswitch 文での分岐ではなく、メソッドチェーンで実装できるのがよい

import nextConnect from "next-connect";

const handler = nextConnect();

handler
  .use(auth)
  .get((req, res) => {
    // For demo purpose only. You will never have an endpoint which returns all users.
    // Remove this in production
    res.json({ users: getAllUsers(req) })
  })
  .post((req, res) => {
    const { username, password, name } = req.body
    if (!username || !password || !name) {
      return res.status(400).send('Missing fields')
    }
    // Here you check if the username has already been used
    const usernameExisted = !!findUserByUsername(req, username)
    if (usernameExisted) {
      return res.status(409).send('The username has already been used')
    }
    const user = { username, password, name }
    // Security-wise, you must hash the password before saving it
    // const hashedPass = await argon2.hash(password);
    // const user = { username, password: hashedPass, name }
    createUser(req, user)
    req.logIn(user, (err) => {
      if (err) throw err
      // Log the signed up user in
      res.status(201).json({
        user,
      })
    })
  })

export default handler;

とてもシンプルに実装できそう

参考

https://serip39.hatenablog.com/entry/2020/08/27/083000#next-connect