我已经看过 Next.js Clerk 与 NextIntl 的对比。中间件冲突
我已经测试了 next-intl 和 clerk v5 之间的集成,并且 /api 文件夹的使用被阻止,因为它引发了 404。看起来在启用 /api 路径并保护它时存在冲突。
这是我在中间件中的配置:
import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server";
import createMiddleware from "next-intl/middleware";
import { NextResponse } from "next/server";
import { defaultLocale, locales } from "./messages/config";
const intlMiddleware = createMiddleware({
locales: locales,
defaultLocale: defaultLocale,
alternateLinks: false,
localePrefix: "as-needed",
});
const isProtectedRoute = createRouteMatcher(["/:locale/(.*)", "/", "/api/:path*"]);
export default clerkMiddleware((auth, req) => {
const { pathname } = req.nextUrl;
if (pathname.includes("/:locale/")) {
const locale = pathname.split("/")[1];
const replacedPathname = pathname.replace("/:locale/", "");
return NextResponse.redirect(
new URL(`/${(locales.includes(locale) ?? locale) || defaultLocale}/${replacedPathname}`, req.url),
);
}
if (isProtectedRoute(req)) {
auth().protect();
}
return intlMiddleware(req);
});
export const config = {
matcher: ["/((?!api/config/:path*).*)", "/((?!_next|_vercel|.*\\..*).*)"],
};
这是我的文件夹结构:
这是我的 .env.local 文件的(一部分):
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/:locale/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/:locale/sign-up
任何有关配置匹配器和保护部分或全部 /api 路由的帮助都会很棒。
我按照指南进行操作,并预计 /api 文件夹将受到保护,但引发了 404。
这就是我所做的。我希望 Clerk 保护某些本地化路由和某些 api 路由。我不希望 Next-Intl 本地化我的 api 路由。
我的文件结构与你的类似,只是我的注册路径是 \sign-up[[...sign-up]]\page.tsx
我使用默认环境配置,效果很好
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
我通过在中间件中这样列出本地化路由来保护它们。
const isProtectedRoute = createRouteMatcher([
"/:locale/dashboard(.*)",
"/:locale/my-account(.*)",
]);
另外,在中间件中,我确保 Clerk 和 Next-Intl 都在除静态页面之外的任何地方运行。我的中间件匹配器如下所示:
export const config = {
matcher: "/((?!static|.*\\..*|_next).*)",
};
在 ClerkMiddleware 内部,我检查 Next-Intl 是否在 api 路由上运行。这是我的代码:
export default clerkMiddleware((auth, req) => {
// Restrict admin routes to users with specific permissions
if (isProtectedRoute(req)) {
auth().protect({});
}
// do not localize api routes
const path = req.nextUrl.pathname;
if (path.includes("/api")) {
return;
}
return intlMiddleware(req);
});
最后在每个 api 路由中我添加了这样的 Clerk 身份验证。
import { auth } from "@clerk/nextjs/server";
export async function POST(request) {
// check if admin
const { has } = auth();
if (!has({ role: "org:admin" })) {
return new Response("You do not have rights", {
status: 401,
});
}
// Here is your route logic
}