infodusha
infodusha10mo ago

Hot to redirect in middleware when using createCallerFactory

Hello. I do have this tiny middleware:
const authMiddleware = middleware(async (opts) => {
const result = await opts.next();
if (!result.ok) {
if (result.error.status === ErrorCode.TOKEN_INVALID) {
redirect('/logout');
}
}
return result;
});
const authMiddleware = middleware(async (opts) => {
const result = await opts.next();
if (!result.ok) {
if (result.error.status === ErrorCode.TOKEN_INVALID) {
redirect('/logout');
}
}
return result;
});
I am aware of redirect throws an error but it seems to be wrapped in a result.error.cause when thrown out so next can't realize that is redirect error and just ouputs Error: NEXT_REDIRECT to console. isRedirectError(result.error) === false while isRedirectError(result.error.cause) === true Is there any known workaround for this to work? Node 20 / npm 10
5 Replies
Nick
Nick10mo ago
This appears to be tRPC working as designed I don’t believe it’s possible to throw a redirect with NextJS APIs from within tRPC You’d need to catch an error and handle it (I can be wrong as I’m not a next user)
infodusha
infodushaOP10mo ago
You’d need to catch an error and handle it
I wish to, the thing is there is no way I can handle it because the error thrown is the handler itself
Nick
Nick10mo ago
You’d throw a bespoke error and then handle that I believe, you can’t use next APIs in tRPC any more than you can use AngularJs in React
infodusha
infodushaOP2mo ago
I imagine this as a flag / API to tell tRPC do not wrap that particular error in TrpcError that i am not aware of Ahh I see your point here A have also tried
const redirectError = getRedirectError('/logout', RedirectType.push, RedirectStatusCode.TemporaryRedirect);
const trpcError = new TRPCError({
message: redirectError.message,
code: 'UNAUTHORIZED',
cause: redirectError.cause,
});
const magicError = Object.assign(redirectError, trpcError);
throw magicError;
const redirectError = getRedirectError('/logout', RedirectType.push, RedirectStatusCode.TemporaryRedirect);
const trpcError = new TRPCError({
message: redirectError.message,
code: 'UNAUTHORIZED',
cause: redirectError.cause,
});
const magicError = Object.assign(redirectError, trpcError);
throw magicError;
to preted that is TRPC error but aparently it is not thrown but just logged. Now the only solution seems to we wrapping the call in api that will allow to throw outside of caller factory (sounds like making a proxy object or so) Since next 15 came out and it has it's own error handling function, the solution I had before (custom webpack plugin) had to be thrown away, so I had this question again And now here is a solution:
const caller = createCallerFactory(apiRouter);
const createContext = cache(async () => {
...
});
export const directApi = caller(createContext, {
onError(ctx) {
if (isNotFoundError(ctx.error.cause) || isRedirectError(ctx.error.cause)) {
throw ctx.error.cause;
}
},
});
const caller = createCallerFactory(apiRouter);
const createContext = cache(async () => {
...
});
export const directApi = caller(createContext, {
onError(ctx) {
if (isNotFoundError(ctx.error.cause) || isRedirectError(ctx.error.cause)) {
throw ctx.error.cause;
}
},
});