3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1人フロントエンドAdvent Calendar 2024

Day 2

Next.jsに追加されたforbiddenとunauthorized機能

Posted at

はじめに

Next.jsのApp Routerはプロジェクトの構造をappディレクトリ内でファイル名とフォルダ名とその組み合わせを元にして決定します。

この記事ではNext.jsのv15.1.0から新たに追加された2つの予約されたファイル名と2つの機能を紹介します。

執筆現在v15.0.4-canary.33canaryとして存在しています。そのためこれから紹介する機能を利用するにはexperimental.authInterruptstrueに設定する必要があります。

next.config.ts
const nextConfig: NextConfig = {
  experimental: {
    authInterrupts: true,
  },
};

追加された機能を利用して作成したデモページを作成しました。実際に触りたい場合はこちらをどうぞ。

forbidden

forbidden.jsnot-found.jsと同じような機能を持つファイルです。同時に追加されたforbidden関数と合わせて権限の不足等のエラー時に利用されます。

ページのUIの作成中にfobiddenが呼び出された時、そのセグメントのpage.jsではなく、403エラーと合わせてforbidden.jsに記述されたUIが表示されます(forbidden.jsがなければNext.jsが用意したデフォルトのUIが表示されます)。

forbidden.jsに遷移する例
import { forbidden } from 'next/navigation'
import { getUser } from '@/model/user'
 
export default async function CreateBlog() {
  const user = await getUser()

  // ブログを作成・編集する権限がなければforbiddenへ移動
  if (!hasWriteBlogPermission(user.permissions)) {
    // returnは不要
    forbidden()
  }

  // 通常表示されるUI
  return (
    <main>
      <CreateBlogForm />
    </main>
  )
}

forbidden関数がサーバーアクション、ルートハンドラ内で実行された場合は、処理を中断してステータスコード403を返します。

forbidden関数を利用した一例
'use server'
 
import { forbidden, notFound } from 'next/navigation'
import { getUser } from '@/model/user'
import { getBlog, updateBlog } from '@/model/blog'
 
export async function update(formData: FormData) {
  const user = await getUser()
  const blog = await getBlog(formData)

  // ブログがない場合は404を返す
  if (!blog) {
    notFound()
  }

  // ブログを記述したユーザーでない場合は403を返す
  if (blog.userId !== user.id) {
    forbidden()
  }
 
  // ブログの更新処理
  // ...
}

unauthorized

unauthorized.jsもまたunauthorized関数と合わせて未ログイン等のエラー時に利用されます。

ページのUIの作成中にunauthorizedが呼び出された時、そのセグメントのpage.jsではなく、401エラーと合わせてunauthorized.jsに記述されたUIが表示されます(unauthorized.jsがなければNext.jsが用意したデフォルトのUIが表示されます)。

unauthorized.jsに遷移する例
import { unauthorized } from 'next/navigation'
import { getUser } from '@/model/user'
 
export default async function CreateBlog() {
  const user = await getUser()

  // ログインしていない場合はunauthorizedへ移動
  if (!user) {
    // returnは不要
    unauthorized()
  }

  // 通常表示されるUI
  return (
    <main>
      <CreateBlogForm />
    </main>
  )
}

unauthorized関数はサーバーアクション、ルートハンドラ内で実行された場合は、処理を中断してステータスコード401を返します。

unauthorized関数を利用した一例
'use server'
 
import { unauthorized, forbidden, notFound } from 'next/navigation'
import { getUser } from '@/model/user'
import { getBlog, updateBlog } from '@/model/blog'
 
export async function update(formData: FormData) {
  const user = await getUser()

  // ログインしていない場合は401を返す
  if (!user) {
    unauthorized()
  }
 
  // ブログの更新処理
  // ...
}

さいごに

Next.jsのcanaryで2つのFile Conventionsが追加され、それに関連する2つのnavigationAPIを紹介しました。
今後も新たな意味を持つファイル名が追加されると考えられるので、現存しないファイル名であっても_を先頭につけるように心がけて行きたいです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?