Files
AFFiNE-Mirror/packages/backend/server/src/base/websocket/adapter.ts
T
EYHN c1691157f9 feat(core): enable socket cors (#12823)
fix android & ios selfhost syncing

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Improved WebSocket connection compatibility by enabling cross-origin
requests with credentials and restricting allowed HTTP methods to GET
and POST.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: fengmk2 <fengmk2@gmail.com>
2025-06-17 09:40:08 +08:00

65 lines
1.8 KiB
TypeScript

import { INestApplication } from '@nestjs/common';
import { IoAdapter } from '@nestjs/platform-socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { Server, Socket } from 'socket.io';
import { Config } from '../config';
import { AuthenticationRequired } from '../error';
import { SocketIoRedis } from '../redis';
import { WEBSOCKET_OPTIONS } from './options';
export class SocketIoAdapter extends IoAdapter {
constructor(private readonly app: INestApplication) {
super(app);
}
override createIOServer(port: number, options?: any): Server {
const config = this.app.get(WEBSOCKET_OPTIONS) as Config['websocket'] & {
canActivate: (socket: Socket) => Promise<boolean>;
};
const server: Server = super.createIOServer(port, {
...config,
...options,
// Enable CORS for Socket.IO
cors: {
origin: true, // Allow all origins
credentials: true, // Allow credentials (cookies, auth headers)
methods: ['GET', 'POST'],
},
});
if (config.canActivate) {
server.use((socket, next) => {
config
.canActivate(socket)
.then(pass => {
if (pass) {
next();
} else {
throw new AuthenticationRequired();
}
})
.catch(e => {
next(e);
});
});
}
const pubClient = this.app.get(SocketIoRedis);
const subClient = pubClient.duplicate();
server.adapter(createAdapter(pubClient, subClient));
const close = server.close;
server.close = async fn => {
await close.call(server, fn);
// NOTE(@forehalo):
// the lifecycle of duplicated redis client will not be controlled by nestjs lifecycle
// we've got to manually disconnect it
subClient.disconnect();
};
return server;
}
}