ファランクスブログ

© 2026 all rights reserved.
  1. blog
  2. middleware
  • Nextjs
  • proxy.ts
  • ライブラリ
  • 例
  • ルート保護
  • 言語の切り替え
  • ルートによる処理の分岐
  • Tanstack
  • createStart
  • createMiddleware
  • 使い方

Nextjs/Tanstack:middleware

2026年6月3日

middleware:

  • Nextjsに固有のものではなく、HTTPリクエストとレスポンスの間で処理を挟むレイヤー

  • リクエストがサーバーに到達する前に処理を挟むことが出来るのが特徴

Nextjs

proxy.ts

import { NextRequest } from "next/server";

export default function proxy(req: NextRequest) {
  console.log("middleware", req);

  return NextResponse.next();
}

export const config = {
  matcher: [
    "/edit/:path*",
    "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
  ],
};
  • proxy()の{}内

    • リクエストの前に実行する内容

  • config.matcher:

    • proxyの内容を実行・除外するルート

    • :path*が付くと「後ろの階層にも適用」という意味

    • 長い行の部分はネガティブマッチャー。ここを書かないと/api/* や _next/static/* にもproxyが走る

  • NextResponse.next():

    • middlewareの処理をそのまま続けて通常通りにリクエストを通す(次に進める)ためのレスポンス

    • NextResponse.next()の部分が無くてもproxyは機能する

ライブラリ

様々なライブラリのDocsにはproxy.tsに書くコードが掲載されているが、大抵ミドルウェア関数がそのままexportされているだけなので、他のproxy処理を書く場所が無い。

next-intlの例:

import createMiddleware from 'next-intl/middleware';
import {routing} from './i18n/routing';

export default createMiddleware(routing);

対策:ラッパー

const intlMiddleware = createMiddleware(routing);

export async function proxy(req: NextRequest) {
  // 処理
  return intlMiddleware(req);
}
  • 上記は自分の処理を行うために、ライブラリのミドルウェア(上記はintlMiddleware)をmiddlewareでラップしている

  • 処理の流れは自分の処理の後にライブラリのミドルウェアが実行される

例

ルート保護

例:ユーザーがログインしていない場合/sign-inにリダイレクト。対象は /edit 以下

import { NextRequest, NextResponse } from "next/server";
import { auth } from "./lib/auth";

export default async function proxy(req: NextRequest) {
  const session = await auth();

  if (!session) {
    return NextResponse.redirect(new URL("/sign-in", req.url));
  }
  return NextResponse.next();
}

export const config = {
  matcher: [
    "/edit/:path*",
    "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
  ],
};
  • 絶対URLとしてリダイレクト先を指定する

    • new URL():req.urlでドメイン部分(xxx.com)を取り出し、そこに左側の相対パスをくっつけてリダイレクト用の絶対URLを生成

言語の切り替え

*next-intlを使っている場合は内部的に自動で行われる

例:リクエストの前にブラウザのaccept-languageに基づいてリダイレクト

import { NextRequest, NextResponse } from "next/server";

export default function proxy(req: NextRequest) {
  const pathname = req.nextUrl.pathname;
  const lang = req.headers.get("accept-language") || "";
  const locale = lang.includes("ja") ? "ja" : "en";

  return NextResponse.redirect(new URL(`/${locale}${pathname}`, req.url));
}

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"],
};
  • *proxyで行うとユーザーが手動で言語を切り替える余地を与えない

ルートによる処理の分岐

以下のようにmatcherで複数パスの指定はできるが、ルート毎にproxy処理を分けたい場合はどうするか

export const config = {
  matcher: ["/api/:path*", "/admin/:path*"], 
};

proxy内で分岐:

export function proxy(req: NextRequest) {
  if (req.nextUrl.pathname.startsWith("/admin")) {
    // /admin/* の処理

  } else if (req.nextUrl.pathname.startsWith("/dashboard")) {
    // /dashboard/* の処理
  }
  return NextResponse.next();
}
  • req.nextUrl.pathname でパスを確認して分岐処理を行う。共通処理は分岐の前に書く

Tanstack

createStart

start.ts:

import { createStart } from '@tanstack/react-start'

const csrfMiddleware = createCsrfMiddleware({
	filter: (ctx) => ctx.handlerType === "serverFn",
});

export const startInstance = createStart(() => {
  return {
    requestMiddleware: [authMiddleware , csrfMiddleware],
  }
})
  • Nextjsのproxy.tsと同じ様なもの

  • 全てのリクエストで実行される。

  • requestMiddlewareにcreateMiddlewareで作成したmiddlewareを入れる。

  • *start.ts を作成しない場合はCORSミドルウェアが自動で設定されるが、start.tsを作成する場合は書く必要がある。

createMiddleware

export const authMiddleware = createMiddleware({ type: 'request' }).server(
  async ({ next, request }) => {

    // /dashboard以下をmiddlewareでチェック。
    const url = new URL(request.url)
    if (
      !url.pathname.startsWith('/dashboard') 
    ) {
      return next()
    }
    const headers = getRequestHeaders()
    const session = await auth.api.getSession({ headers })

    if (!session) {
      throw redirect({
        to: '/',
      })
    }
    return next({
      context: {
        session,
      },
    })
  },
)
  • type:

    • request:すべてのリクエストの前に走る。

    • function:関数の実行前に走る。

  • context:

    • 次の処理にmiddlewareで取得したUser情報等の値を渡せる。

使い方

type:requst

export const Route = createFileRoute('/')({
  component: RouteComponent,
  server:{
    middleware:[authMiddleware]
  },
  • ルート定義ファイル、あるいはglobal middleware(createStart)に書く。

type:function

export const getFn = createServerFn({
  method: 'GET',
}).
middleware([authFnMiddleware])
.handler(async ({ data, context }) => {
}
  • 関数ごとに使う。

nextjs
/
tanstack
  • Nextjs
  • proxy.ts
  • ライブラリ
  • 例
  • ルート保護
  • 言語の切り替え
  • ルートによる処理の分岐
  • Tanstack
  • createStart
  • createMiddleware
  • 使い方