Files
leaudit-platform-frontend/app/utils/server-auth-handler.ts
T
2025-11-18 11:06:24 +08:00

73 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 服务端认证错误处理工具
*
* 用于在 Remix loader/action 中统一处理 AuthenticationErrortoken 过期)
*/
import { redirect } from "@remix-run/node";
/**
* 包装服务端异步函数,自动处理 AuthenticationError
*
* @param fn - 需要执行的异步函数
* @param pathname - 当前路径(用于保存重定向目标)
* @returns 函数执行结果,或在 token 过期时重定向到登录页
*
* @example
* // 在 loader 中使用
* export async function loader({ request }: LoaderFunctionArgs) {
* const url = new URL(request.url);
*
* return handleServerAuth(async () => {
* const { getUserSession } = await import("~/api/login/auth.server");
* const { frontendJWT } = await getUserSession(request);
*
* // 调用需要认证的 API
* const response = await getDocumentTypes({}, frontendJWT);
*
* return Response.json({ data: response.data });
* }, url.pathname);
* }
*/
export async function handleServerAuth<T>(
fn: () => Promise<T>,
pathname: string
): Promise<T> {
try {
return await fn();
} catch (error) {
// 检查是否是 AuthenticationErrortoken 过期)
if (error instanceof Error && error.name === 'AuthenticationError') {
console.warn(`⚠️ [Server Auth Handler] Token 过期,重定向到登录页 (from: ${pathname})`);
// 保存当前路径,登录后可以跳转回来
const redirectTo = pathname !== '/login' ? pathname : '/';
throw redirect(`/login?redirect=${encodeURIComponent(redirectTo)}`);
}
// 其他错误继续抛出
throw error;
}
}
/**
* 检查错误是否是 AuthenticationError
*
* @param error - 要检查的错误对象
* @returns 是否是 AuthenticationError
*/
export function isAuthenticationError(error: unknown): boolean {
return error instanceof Error && error.name === 'AuthenticationError';
}
/**
* 从 AuthenticationError 创建登录重定向
*
* @param pathname - 当前路径
* @returns Remix redirect Response
*/
export function redirectToLogin(pathname: string) {
const redirectTo = pathname !== '/login' ? pathname : '/';
return redirect(`/login?redirect=${encodeURIComponent(redirectTo)}`);
}