Refactor catching of error from API : check the type of errors
This commit is contained in:
parent
891ad2c34a
commit
e45fcb371c
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB |
21
messages/JsonMessages/ErrorApiData.ts
Normal file
21
messages/JsonMessages/ErrorApiData.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING! The original file is in /messages/JsonMessages.
|
||||||
|
* All other files are automatically copied from this file on container startup / build
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const isErrorApiData = z.object({
|
||||||
|
type: z.string(),
|
||||||
|
code: z.string(),
|
||||||
|
title: z.string(),
|
||||||
|
subtitle: z.string(),
|
||||||
|
details: z.string(),
|
||||||
|
image: z.string(),
|
||||||
|
urlToRedirect: z.optional(z.nullable(z.string())),
|
||||||
|
buttonTitle: z.optional(z.nullable(z.string())),
|
||||||
|
timeToRetry: z.optional(z.nullable(z.bigint())),
|
||||||
|
canRetryManual: z.optional(z.nullable(z.boolean()))
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ErrorApiData = z.infer<typeof isErrorApiData>;
|
@ -1,6 +1,7 @@
|
|||||||
import { Server } from "hyper-express";
|
import { Server } from "hyper-express";
|
||||||
import Response from "hyper-express/types/components/http/Response";
|
import Response from "hyper-express/types/components/http/Response";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import {isErrorApiData} from "../Messages/JsonMessages/ErrorApiData";
|
||||||
|
|
||||||
export class BaseHttpController {
|
export class BaseHttpController {
|
||||||
constructor(protected app: Server) {
|
constructor(protected app: Server) {
|
||||||
@ -31,14 +32,15 @@ export class BaseHttpController {
|
|||||||
|
|
||||||
if (axios.isAxiosError(e) && e.response) {
|
if (axios.isAxiosError(e) && e.response) {
|
||||||
res.status(e.response.status);
|
res.status(e.response.status);
|
||||||
if (!e.response.data?.code) {
|
const errorType = isErrorApiData.safeParse(e?.response?.data);
|
||||||
|
if (!errorType.success) {
|
||||||
res.send(
|
res.send(
|
||||||
"An error occurred: " +
|
"An error occurred: " +
|
||||||
e.response.status +
|
e.response.status +
|
||||||
" " +
|
" " +
|
||||||
(e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText)
|
(e.response.data && e.response.data.message ? e.response.data.message : e.response.statusText)
|
||||||
);
|
);
|
||||||
} else res.json(e.response.data);
|
} else res.json(errorType.data);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
res.status(500);
|
res.status(500);
|
||||||
|
@ -41,6 +41,7 @@ import { localWokaService } from "../Services/LocalWokaService";
|
|||||||
import { WebSocket } from "uWebSockets.js";
|
import { WebSocket } from "uWebSockets.js";
|
||||||
import { WokaDetail } from "../Messages/JsonMessages/PlayerTextures";
|
import { WokaDetail } from "../Messages/JsonMessages/PlayerTextures";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import {ErrorApiData, isErrorApiData} from "../Messages/JsonMessages/ErrorApiData";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object passed between the "open" and the "upgrade" methods when opening a websocket
|
* The object passed between the "open" and the "upgrade" methods when opening a websocket
|
||||||
@ -68,13 +69,21 @@ interface UpgradeData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UpgradeFailedData {
|
interface UpgradeFailedInvalidData {
|
||||||
rejected: true;
|
rejected: true;
|
||||||
reason: "tokenInvalid" | "textureInvalid" | "error" | null;
|
reason: "tokenInvalid" | "textureInvalid" | null;
|
||||||
message: string;
|
message: string;
|
||||||
roomId: string;
|
roomId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface UpgradeFailedErrorData {
|
||||||
|
rejected: true;
|
||||||
|
reason: "error";
|
||||||
|
error: ErrorApiData;
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpgradeFailedData = UpgradeFailedErrorData | UpgradeFailedInvalidData;
|
||||||
|
|
||||||
export class IoSocketController {
|
export class IoSocketController {
|
||||||
private nextUserId: number = 1;
|
private nextUserId: number = 1;
|
||||||
|
|
||||||
@ -314,35 +323,23 @@ export class IoSocketController {
|
|||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (Axios.isAxiosError(err)) {
|
if (Axios.isAxiosError(err)) {
|
||||||
if (err?.response?.status == 404 || !err?.response?.data.code) {
|
const errorType = isErrorApiData.safeParse(err?.response?.data);
|
||||||
// If we get an HTTP 404, the token is invalid. Let's perform an anonymous login!
|
if(errorType.success) {
|
||||||
|
return res.upgrade(
|
||||||
console.warn(
|
{
|
||||||
'Cannot find user with email "' +
|
rejected: true,
|
||||||
(userIdentifier || "anonymous") +
|
reason: "error",
|
||||||
'". Performing an anonymous login instead.'
|
status: err?.response?.status,
|
||||||
);
|
error: errorType.data,
|
||||||
} else if (err?.response?.data.code) {
|
} as UpgradeFailedData,
|
||||||
//OLD // If we get an HTTP 403, the world is full. We need to broadcast a special error to the client.
|
websocketKey,
|
||||||
//OLD // we finish immediately the upgrade then we will close the socket as soon as it starts opening.
|
websocketProtocol,
|
||||||
return res.upgrade(
|
websocketExtensions,
|
||||||
{
|
context
|
||||||
rejected: true,
|
);
|
||||||
reason: "error",
|
}
|
||||||
message: err?.response?.data.code,
|
|
||||||
status: err?.response?.status,
|
|
||||||
error: err?.response?.data,
|
|
||||||
roomId,
|
|
||||||
} as UpgradeFailedData,
|
|
||||||
websocketKey,
|
|
||||||
websocketProtocol,
|
|
||||||
websocketExtensions,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
memberMessages = userData.messages;
|
memberMessages = userData.messages;
|
||||||
memberTags = userData.tags;
|
memberTags = userData.tags;
|
||||||
@ -487,7 +484,7 @@ export class IoSocketController {
|
|||||||
} else if (ws.reason === "textureInvalid") {
|
} else if (ws.reason === "textureInvalid") {
|
||||||
socketManager.emitInvalidTextureMessage(ws);
|
socketManager.emitInvalidTextureMessage(ws);
|
||||||
} else if (ws.reason === "error") {
|
} else if (ws.reason === "error") {
|
||||||
socketManager.emitErrorScreenMessage(ws, ws.error as ErrorScreenMessage);
|
socketManager.emitErrorScreenMessage(ws, ws.error);
|
||||||
} else {
|
} else {
|
||||||
socketManager.emitConnexionErrorMessage(ws, ws.message);
|
socketManager.emitConnexionErrorMessage(ws, ws.message);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ import Debug from "debug";
|
|||||||
import { ExAdminSocketInterface } from "../Model/Websocket/ExAdminSocketInterface";
|
import { ExAdminSocketInterface } from "../Model/Websocket/ExAdminSocketInterface";
|
||||||
import { compressors } from "hyper-express";
|
import { compressors } from "hyper-express";
|
||||||
import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
import { isMapDetailsData } from "../Messages/JsonMessages/MapDetailsData";
|
||||||
|
import {ErrorApiData} from "../Messages/JsonMessages/ErrorApiData";
|
||||||
|
|
||||||
const debug = Debug("socket");
|
const debug = Debug("socket");
|
||||||
|
|
||||||
@ -644,9 +645,22 @@ export class SocketManager implements ZoneEventListener {
|
|||||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public emitErrorScreenMessage(client: compressors.WebSocket, error: ErrorScreenMessage) {
|
public emitErrorScreenMessage(client: compressors.WebSocket, error: ErrorApiData) {
|
||||||
|
const errorMessage = new ErrorScreenMessage();
|
||||||
|
errorMessage.setType(error.type);
|
||||||
|
errorMessage.setCode(error.code);
|
||||||
|
errorMessage.setTitle(error.title);
|
||||||
|
errorMessage.setSubtitle(error.subtitle);
|
||||||
|
errorMessage.setDetails(error.details);
|
||||||
|
errorMessage.setImage(error.image);
|
||||||
|
|
||||||
|
if(error.urlToRedirect) errorMessage.setUrltoredirect(error.urlToRedirect);
|
||||||
|
if(error.buttonTitle) errorMessage.setButtontitle(error.buttonTitle);
|
||||||
|
if(!!error.canRetryManual) errorMessage.setCanretrymanual(error.canRetryManual);
|
||||||
|
if(error.timeToRetry) errorMessage.setTimetoretry(error.timeToRetry);
|
||||||
|
|
||||||
const serverToClientMessage = new ServerToClientMessage();
|
const serverToClientMessage = new ServerToClientMessage();
|
||||||
serverToClientMessage.setErrorscreenmessage(error);
|
serverToClientMessage.setErrorscreenmessage(errorMessage);
|
||||||
|
|
||||||
//if (!client.disconnecting) {
|
//if (!client.disconnecting) {
|
||||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||||
|
Loading…
Reference in New Issue
Block a user