如何在SvelteKit的tRPC错误处理中实现页面重定向?
解决tRPC + SvelteKit中401未授权重定向问题
直接在tRPC的onError回调中throw redirect()无效的原因是:该回调属于tRPC内部错误处理流程,抛出的错误会被tRPC捕获并转化为HTTP响应,无法触发SvelteKit的重定向逻辑。以下是两种可行的解决方案:
方案一:在createContext阶段提前校验身份(推荐)
在创建tRPC上下文时就完成用户身份校验,未认证直接抛出重定向,避免进入路由处理环节,更高效:
// $lib/trpc/context.ts import { redirect } from '@sveltejs/kit'; import type { RequestEvent } from '@sveltejs/kit'; export async function createContext(event: RequestEvent) { // 替换为你的实际身份校验逻辑(比如从Cookie/Session获取用户) const user = await fetchCurrentUserFromSession(event); if (!user) { // 未认证直接触发重定向 throw redirect(307, '/login'); } return { user, event // 将event存入上下文,方便后续使用 }; }
方案二:在tRPC onError中修改响应实现重定向
如果需要针对特定路由的UNAUTHORIZED错误处理(比如部分路由允许匿名访问),可以通过上下文传递SvelteKit的event对象,直接修改响应头实现重定向:
修改hooks.server.ts:
import { createContext } from '$lib/trpc/context'; import { router } from '$lib/trpc/router'; import type { Handle } from '@sveltejs/kit'; import { createTRPCHandle } from 'trpc-sveltekit'; import { getHTTPStatusCodeFromError } from '@trpc/server/http'; import type { TRPCError } from '@trpc/server'; const trpcHandleError = ({ error, ctx }) => { console.error(`tRPC error [${error.code}] @ ${error.path}:`, error.message); const httpStatus = getHTTPStatusCodeFromError(error as TRPCError); const event = ctx?.event; if (httpStatus === 401 && event) { // 直接设置重定向响应 event.response = new Response(null, { status: 307, headers: { Location: '/login' } }); } else if (httpStatus === 403 && event) { // 返回404响应 event.response = new Response('Not Found', { status: 404 }); } }; export const handle: Handle = async ({ event, resolve }) => { // 调用tRPC处理函数,并传入event到context const trpcResult = await createTRPCHandle({ router, createContext: () => createContext(event), onError: trpcHandleError })({ event, resolve }); // 如果tRPC已生成响应,直接返回 if (trpcResult) return trpcResult; // 处理非tRPC请求 return resolve(event); };
补充:客户端调用的错误处理
如果是在Svelte组件中调用tRPC客户端,需要在客户端错误回调中处理重定向:
// $lib/trpc/client.ts import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'; import type { Router } from '$lib/trpc/router'; import { goto } from '$app/navigation'; export const trpc = createTRPCProxyClient<Router>({ links: [ httpBatchLink({ url: '/api/trpc' }) ], onError: (error) => { if (error.data?.httpStatus === 401) { goto('/login'); } } });
内容的提问来源于stack exchange,提问作者Basil
相关产品推荐
相关产品推荐

