Skip to content

Add support for Fastify #117

@crisz

Description

@crisz

I have a Fastify project where I use better-auth to expose the authentication endpoints.
Currently, the standard approach is using toNodeHandler along with Fastify's reply.hijack(), in order to pass the raw request and reply, releasing Fastify from the duty of managing the request internal state.

The problem with this approach is that it completely bypasses Fastify's outbound lifecycle. Because of this, standard plugins like @fastify/cors or @fastify/compress silently break on these routes, and we are forced to manually extract and pipe headers to the raw Node res object to make things work:

fastify.all(
      '/api/auth/*',
      { config: { skipSessionPopulation: true } },
      async (request: FastifyRequest, reply: FastifyReply) => {
        // Since we hijack the reply, we must manually flush headers set by Fastify (e.g. CORS)
        for (const [key, value] of Object.entries(reply.getHeaders())) {
          if (value !== undefined) {
             reply.raw.setHeader(key, value as string | number | readonly string[]);
          }
        }
        
        await nodeHandler(request.raw, reply.raw);

        // We use reply.hijack() so Fastify does not attempt to serialise the
        // response after better-auth has already written to "reply".
        reply.hijack();
      },
    );

I think that a nativetoFastifyHandler adapter is needed in order to avoid the explicit copy of headers towards the raw object, and to prevent lifecycle-related plugins to break.

Instead of taking over the raw Node socket, it could map the incoming request to a standard Web Request, get the Response from better-call, and simply pass it back to Fastify using reply.send().

This would keep Fastify in charge and plays nicely with the rest of its ecosystem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions