Create websocket exception filter
parent
e323623007
commit
5d55631812
|
|
@ -1,4 +1,4 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Injectable, Logger, UseFilters } from '@nestjs/common';
|
||||
import {
|
||||
ConnectedSocket,
|
||||
OnGatewayConnection,
|
||||
|
|
@ -10,6 +10,8 @@ import { PlayerService } from './players/player.service';
|
|||
import { GameService } from 'src/games/game.service';
|
||||
import { Socket } from 'socket.io';
|
||||
import { ClientEvent, CreateLobbyEvent, JoinLobbyEvent } from 'interface';
|
||||
import { WsExceptionFilter } from './websocket-exception-filter';
|
||||
import { PlayerNotFoundException } from './exceptions';
|
||||
|
||||
@WebSocketGateway({ cors: true })
|
||||
@Injectable()
|
||||
|
|
@ -24,6 +26,7 @@ export class AppService implements OnGatewayConnection {
|
|||
this.playerService.createPlayer(client.id);
|
||||
}
|
||||
|
||||
@UseFilters(new WsExceptionFilter([PlayerNotFoundException]))
|
||||
@SubscribeMessage(ClientEvent.CREATE_LOBBY)
|
||||
handleCreateLobby(
|
||||
@ConnectedSocket() client: Socket,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
import { WsException } from '@nestjs/websockets';
|
||||
import { ErrorCode } from 'interface';
|
||||
|
||||
export abstract class WebSocketException extends WsException {
|
||||
public readonly errorCode: ErrorCode;
|
||||
|
||||
constructor(message: string, errorCode: ErrorCode) {
|
||||
super(message);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
}
|
||||
|
||||
export class PlayerNotFoundException extends WebSocketException {
|
||||
constructor(playerId: string) {
|
||||
super(
|
||||
'Unable to find player from ID: ' + playerId,
|
||||
ErrorCode.PLAYER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class GameNotFoundException extends WebSocketException {
|
||||
constructor(gameId: string) {
|
||||
super(
|
||||
'Unable to find game from ID: ' + gameId,
|
||||
ErrorCode.GAME_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Player } from './player';
|
||||
import { PlayerNotFoundException } from 'src/exceptions';
|
||||
|
||||
@Injectable()
|
||||
export class PlayerService {
|
||||
|
|
@ -17,6 +18,10 @@ export class PlayerService {
|
|||
|
||||
getPlayer(socketId: string) {
|
||||
this.logger.log(this.players.get(socketId).userName);
|
||||
const player = this.players.get(socketId);
|
||||
if (!player) {
|
||||
throw new PlayerNotFoundException(socketId);
|
||||
}
|
||||
return this.players.get(socketId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import { ArgumentsHost, Catch, Logger } from '@nestjs/common';
|
||||
import { BaseWsExceptionFilter } from '@nestjs/websockets';
|
||||
import { GameNotFoundException, PlayerNotFoundException, WebSocketException } from './exceptions';
|
||||
import { Socket } from 'socket.io';
|
||||
import { ClientEvent } from 'interface';
|
||||
import { emitCreateLobbyError } from 'interface';
|
||||
|
||||
@Catch(PlayerNotFoundException, GameNotFoundException)
|
||||
export class WsExceptionFilter extends BaseWsExceptionFilter<WebSocketException> {
|
||||
private readonly logger = new Logger(BaseWsExceptionFilter.name);
|
||||
private readonly caughtExceptions: (typeof WebSocketException)[];
|
||||
|
||||
constructor(caughtExceptions: (typeof WebSocketException)[]) {
|
||||
super();
|
||||
this.caughtExceptions = caughtExceptions;
|
||||
}
|
||||
|
||||
catch(exception: WebSocketException, host: ArgumentsHost) {
|
||||
const socket = host.switchToWs().getClient() as Socket;
|
||||
const method = host.switchToWs().getPattern();
|
||||
const data: object = host.switchToWs().getData();
|
||||
this.logger.log(
|
||||
`Caught exception: ${exception}
|
||||
for request to ${method}
|
||||
from client ${socket.id}
|
||||
with input ${data}`,
|
||||
);
|
||||
|
||||
if (
|
||||
!this.caughtExceptions.find(
|
||||
(caughtException) => exception instanceof caughtException,
|
||||
)
|
||||
) {
|
||||
this.logger.fatal("Uncaught exception", exception)
|
||||
super.catch(exception, host);
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case ClientEvent.CREATE_LOBBY:
|
||||
emitCreateLobbyError(socket, { error: exception.errorCode });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
export * from "./constants/TrackType";
|
||||
export * from "./server-events/CreateLobbyError";
|
||||
export * from "./server-events/ServerError";
|
||||
export * from "./server-events/ServerEvent";
|
||||
export * from "./server-events/UpdateLobbyEvent";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
import { Socket as ServerSocket } from "socket.io";
|
||||
import { Socket as ClientSocket } from "socket.io-client";
|
||||
import { ErrorCode, ServerError } from "./ServerError";
|
||||
|
||||
export type CreateLobbyError = {
|
||||
error: ErrorCode.PLAYER_NOT_FOUND | ErrorCode.GAME_NOT_FOUND;
|
||||
};
|
||||
|
||||
export const emitCreateLobbyError = (
|
||||
socket: ServerSocket,
|
||||
payload: CreateLobbyError,
|
||||
) => {
|
||||
socket.emit(ServerError.CREATE_LOBBY_ERROR, payload);
|
||||
};
|
||||
|
||||
export const attachHandlerToCreateLobbyError = (
|
||||
socket: ClientSocket,
|
||||
handler: (payload: CreateLobbyError) => void,
|
||||
): (() => void) => {
|
||||
socket.on(ServerError.CREATE_LOBBY_ERROR, handler);
|
||||
return () => socket.off(ServerError.CREATE_LOBBY_ERROR);
|
||||
};
|
||||
|
|
@ -2,3 +2,8 @@ export enum ServerError {
|
|||
CREATE_LOBBY_ERROR = "create-lobby-error",
|
||||
JOIN_LOBBY_ERROR = "join-lobby-error",
|
||||
}
|
||||
|
||||
export enum ErrorCode {
|
||||
PLAYER_NOT_FOUND = "player-not-found",
|
||||
GAME_NOT_FOUND = "game-not-found",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const root = ReactDOM.createRoot(
|
|||
document.getElementById("root") as HTMLElement,
|
||||
);
|
||||
const socket = io("http://localhost:3010");
|
||||
socket.on("exception", console.log);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App socket={socket} />
|
||||
|
|
|
|||
Loading…
Reference in New Issue