forked from mosaicstack/stack
Co-authored-by: Jason Woltje <[email protected]> Co-committed-by: Jason Woltje <[email protected]>
47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
import { toNodeHandler } from 'better-auth/node';
|
|
import type { Auth } from '@mosaic/auth';
|
|
import type { NestFastifyApplication } from '@nestjs/platform-fastify';
|
|
import { AUTH } from './auth.tokens.js';
|
|
|
|
export function mountAuthHandler(app: NestFastifyApplication): void {
|
|
const auth = app.get<Auth>(AUTH);
|
|
const nodeHandler = toNodeHandler(auth);
|
|
|
|
const fastify = app.getHttpAdapter().getInstance();
|
|
|
|
// Use Fastify's addHook to intercept auth requests at the raw HTTP level,
|
|
// before Fastify's body parser runs. This avoids conflicts with NestJS's
|
|
// custom content-type parser.
|
|
fastify.addHook(
|
|
'onRequest',
|
|
(
|
|
req: { raw: IncomingMessage; url: string },
|
|
reply: { raw: ServerResponse; hijack: () => void },
|
|
done: () => void,
|
|
) => {
|
|
if (!req.url.startsWith('/api/auth/')) {
|
|
done();
|
|
return;
|
|
}
|
|
|
|
reply.hijack();
|
|
nodeHandler(req.raw as IncomingMessage, reply.raw as ServerResponse)
|
|
.then(() => {
|
|
if (!reply.raw.writableEnded) {
|
|
reply.raw.end();
|
|
}
|
|
})
|
|
.catch((err: unknown) => {
|
|
if (!reply.raw.headersSent) {
|
|
reply.raw.writeHead(500, { 'Content-Type': 'application/json' });
|
|
}
|
|
if (!reply.raw.writableEnded) {
|
|
reply.raw.end(JSON.stringify({ error: 'Internal auth error' }));
|
|
}
|
|
console.error('[AUTH] Handler error:', err);
|
|
});
|
|
},
|
|
);
|
|
}
|