skylerdj
skylerdj3d ago

Calling Express `request.send` inside tRPC middleware/procedures

Hello 👋! I've been trying to introduce tRPC to our existing express codebase and I was wondering if it's possible to invoke express request.send inside my tRPC middleware or procedures. I want to avoid rewriting our entire auth layer which is unfortunately deeply coupled with the express request/response objects, and instead just call our existing express middleware functions. However I want to make sure doing so isn't going to cause any memory leaks or hanging promises or anything which could silently brick the whole server. Will the tRPC handler return or exit gracefully if the request is closed? Has anyone had experience with this? example:
export const createContext = async ({ req, res }: trpcExpress.CreateExpressContextOptions) => {
// include the request and response objects to be used in procedures
return { req, res };
};

export const protectedProcedure = t.procedure.use(async function isAuthenticated(opts) {
const { req } = opts.ctx;

// this will call res.status(401).send("UNAUTHORIZED") if the token is invalid
// but it's not a simple function and i would have to rewrite our whole auth layer to decouple it from the req/res
await runJWTValidations(req, res);

const token = getTokenFromRequest(req);

const user = await getUserFromToken(token);

if (!user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}

return opts.next({
ctx: { ...opts.ctx, user },
});
});
export const createContext = async ({ req, res }: trpcExpress.CreateExpressContextOptions) => {
// include the request and response objects to be used in procedures
return { req, res };
};

export const protectedProcedure = t.procedure.use(async function isAuthenticated(opts) {
const { req } = opts.ctx;

// this will call res.status(401).send("UNAUTHORIZED") if the token is invalid
// but it's not a simple function and i would have to rewrite our whole auth layer to decouple it from the req/res
await runJWTValidations(req, res);

const token = getTokenFromRequest(req);

const user = await getUserFromToken(token);

if (!user) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}

return opts.next({
ctx: { ...opts.ctx, user },
});
});
Solution:
@Alex / KATT 🐱: You can pass a fake res-object to await runJWTValidations(req, res) Example that probably needs some modification: ```ts const mockRes = {...
Jump to solution
1 Reply
Solution
skylerdj
skylerdj2d ago
@Alex / KATT 🐱: You can pass a fake res-object to await runJWTValidations(req, res) Example that probably needs some modification:
const mockRes = {
// replace the method here
status: () => mockRes,
write: () => mockRes,
send: () => mockRes,
end: () => { },
} satisfies Partial<trpcExpress.CreateExpressContextOptions['res']>

await runJWTValidations(req, mockRes as trpcExpress.CreateExpressContextOptions['res']);
const mockRes = {
// replace the method here
status: () => mockRes,
write: () => mockRes,
send: () => mockRes,
end: () => { },
} satisfies Partial<trpcExpress.CreateExpressContextOptions['res']>

await runJWTValidations(req, mockRes as trpcExpress.CreateExpressContextOptions['res']);