MrJohzM
tRPC10mo ago
6 replies
MrJohz

How can I access the session in fastify when using `useWSS: true`?

I've got a fastify/trpc application that looks something like this:

  await using app = Fastify({
    loggerInstance: logger,
    bodyLimit: 5 * 1024 * 1024,
    https: stores.config.sslOptions ?? null,
    maxParamLength: 5000,
  });

  app.register(ws);
  app.register(fastifyCookie);
  app.register(fastifySession, {
    secret: "super secret, don't look at me",
  });

  function createContext({ req }: CreateFastifyContextOptions) {
    console.log(req.session); // logs "undefined"
    return {};
  }

  app.register(fastifyTRPCPlugin, {
    prefix: "/trpc",
    useWSS: true,
    keepAlive: { enabled: true, pingMs: 50 * 1000 },
    trpcOptions: { router, onError, createContext },
  });


I would expect that the req in the
createContext
function would have access to the session (and it does if useWSS is false). However, when using TRPC with websockets, it currently consistently logs
undefined
.

I assume this is because I'm misconfiguring something somewhere, but I'm not sure what, and I'm not sure how to solve this. Has anyone experienced this, or does anyone have any suggestions about how to resolve this? Thanks in advance!
Solution
Hi @Mr. Joker, I ended up writing my solution up on my blog, you can read that here: https://jonathan-frere.com/posts/trpc-fastify-websockets/

Specifically, the solution I found was this:

// create a new scope so that the hook we add later will only
// affect tRPC-specific requests
app.register((app) => {
  // use a WeakMap to avoid leaking memory by holding on to
  // requests longer than necessary
  const REQS = new WeakMap<
    FastifyRequest | IncomingMessage,
    FastifyRequest
  >();

  app.addHook("onRequest", async (req) => {
    // associate each raw `IncomingMessage` (`req.raw`) with
    // the original `IncomingMessage`
    REQS.set(req.raw, req);
  });

  app.register(fastifyTRPCPlugin, {
    prefix: "/trpc",
    useWSS: true,
    trpcOptions: {
      router,
      onError,
      createContext: ({ req }) => {
        // given either a `FastifyRequest` or an
        // `IncomingMessage`, fetch the related
        // `FastifyRequest` that we saved earlier
        const realReq = REQS.get(req.raw ?? req);
        if (!realReq)
          throw new Error("This should never happen");

        console.log(realReq.session); // logs the session object
        return {};
      },
    },
  });
});
This is a quick post to point out a potential issue that might catch you out with using Fastify’s sessions mechanism alongside tRPC’s websockets transport, and how I’ve fixed it in my projects.
The problem happens with an application that looks something like this:
const app = Fastify(); app.register(ws); app.register(fastifyCookie); app.r...
Was this page helpful?