WebSockets working

This commit is contained in:
2021-06-04 15:19:06 +02:00
parent 787b198ffc
commit 43f26e8ea9
2 changed files with 117 additions and 42 deletions

View File

@ -162,20 +162,23 @@ export class Session {
const host = this.server.host;
const protocols = this.server.protocols;
/*
if ("ws" in protocols) {
this.websocket = new WebSocket(`ws://${host}:${protocols.ws}/_usimp/websocket`, ["usimp"]);
if ("wss" in protocols) {
this.websocket = new WebSocket(`wss://${host}:${protocols.wss}/_usimp/websocket`, ["usimp"]);
this.websocket.addEventListener("error", (error) => {
console.error(error);
this.websocket = null;
});
}
*/
// TODO http -> https
if (protocols) {
this.httpBaseUrl = `http://${host}:${protocols.http}/_usimp`;
if ("https" in protocols) {
this.httpBaseUrl = `https://${host}:${protocols.https}/_usimp`;
try {
return await this.ping();
} catch {
this.domain.invalidServers.push(this.server);
this.server = null;
if (this.server !== null) {
this.domain.invalidServers.push(this.server);
this.server = null;
}
}
} else {
console.warn(`Domain server ${this.server} does not support 'https' transport protocol`);
@ -186,39 +189,111 @@ export class Session {
return undefined;
}
waitForWebSocket() {
if (this.websocket === null) throw Error("websocket not initialized");
return new Promise<void>((resolve, reject) => {
if (this.websocket?.readyState === this.websocket?.OPEN) {
resolve();
} else {
const handlerOpen = () => {
this.websocket?.removeEventListener("open", handlerOpen);
resolve();
};
const handlerError = (error: any) => {
this.websocket?.removeEventListener("error", handlerError);
reject(error);
}
this.websocket?.addEventListener("open", handlerOpen);
this.websocket?.addEventListener("error", handlerError);
}
});
}
waitForWebSocketResponse(req_nr: number, timeout: number) {
if (this.websocket === null) throw Error("websocket not initialized");
return new Promise<any>((resolve, reject) => {
const handlerMsg = (msg: any) => {
const data = JSON.parse(msg.data);
if (data['request_nr'] === req_nr) {
clearTimeout(timer);
this.websocket?.removeEventListener("message", handlerMsg);
this.websocket?.removeEventListener("error", handlerError);
resolve(data);
}
}
const handlerError = (error: any) => {
clearTimeout(timer);
this.websocket?.removeEventListener("message", handlerMsg);
this.websocket?.removeEventListener("error", handlerError);
reject(error);
}
const handlerTimeout = () => {
this.websocket?.removeEventListener("message", handlerMsg);
this.websocket?.removeEventListener("error", handlerError);
reject(Error("timeout"));
}
const timer = setTimeout(handlerTimeout, timeout);
this.websocket?.addEventListener("message", handlerMsg);
this.websocket?.addEventListener("error", handlerError);
});
}
async send(endpoint: string, data: object, timeout: number = 2000, forceHttp: boolean = false) {
this.numRequests++;
if (!forceHttp && this.websocket) {
this.websocket.send(JSON.stringify({
'request_num': this.numRequests,
'data': data
}));
} else {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
while (true) {
try {
if (!forceHttp && this.websocket) {
const req_nr = this.numRequests;
const response = this.waitForWebSocketResponse(req_nr, timeout);
let headers: Record<string, string> = {
'Content-Type': 'application/json',
'To-Domain': this.domain.id,
};
if (this.token) {
headers['Authorization'] = `usimp ${this.token}`;
const startTime = performance.now();
await this.waitForWebSocket();
await this.websocket.send(JSON.stringify({
'request_nr': req_nr,
'endpoint': endpoint,
'to_domain': this.domain.id,
'data': data
}));
const responseData = await response;
const endTime = performance.now();
responseData.duration = endTime - startTime;
return responseData;
} else {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeout);
let headers: Record<string, string> = {
'Content-Type': 'application/json',
'To-Domain': this.domain.id,
};
if (this.token) {
headers['Authorization'] = `usimp ${this.token}`;
}
const startTime = performance.now();
const response = await fetch(`${this.httpBaseUrl}/${endpoint}`, {
method: "POST",
headers: headers,
body: JSON.stringify(data),
signal: controller.signal,
});
clearTimeout(timer);
const responseData = await response.json();
const endTime = performance.now();
responseData.duration = endTime - startTime;
return responseData;
}
} catch (error) {
console.error(error);
if (this.server !== null) {
this.domain.invalidServers.push(this.server);
this.server = null;
}
await this.chooseDomainServer();
}
const startTime = new Date();
const response = await fetch(`${this.httpBaseUrl}/${endpoint}`, {
method: "POST",
headers: headers,
body: JSON.stringify(data),
signal: controller.signal,
});
const endTime = new Date();
clearTimeout(timer);
const responseData = await response.json();
responseData.duration = endTime.getUTCMilliseconds() - startTime.getUTCMilliseconds();
return responseData;
}
}