First pass at converting websocket to send a token along with every call

This commit is contained in:
Dane Everitt 2019-09-24 20:20:29 -07:00
parent 513965dac7
commit 18c4b951e6
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
8 changed files with 143 additions and 135 deletions

View file

@ -1,9 +1,17 @@
import http from '@/api/http';
export default (server: string): Promise<string> => {
interface Response {
token: string;
socket: string;
}
export default (server: string): Promise<Response> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${server}/websocket`)
.then(response => resolve(response.data.data.socket))
.then(({ data }) => resolve({
token: data.data.token,
socket: data.data.socket,
}))
.catch(reject);
});
};

View file

@ -1,6 +1,7 @@
import React, { useEffect } from 'react';
import { Websocket } from '@/plugins/Websocket';
import { ServerContext } from '@/state/server';
import getWebsocketToken from '@/api/server/getWebsocketToken';
export default () => {
const server = ServerContext.useStoreState(state => state.server.data);
@ -15,15 +16,18 @@ export default () => {
return;
}
const socket = new Websocket(server.uuid);
const socket = new Websocket();
socket.on('SOCKET_OPEN', () => setConnectionState(true));
socket.on('SOCKET_CLOSE', () => setConnectionState(false));
socket.on('SOCKET_ERROR', () => setConnectionState(false));
socket.on('status', (status) => setServerStatus(status));
socket.connect()
.then(() => setInstance(socket))
getWebsocketToken(server.uuid)
.then(data => {
socket.setToken(data.token).connect(data.socket);
setInstance(socket);
})
.catch(error => console.error(error));
return () => {
@ -36,8 +40,8 @@ export default () => {
// exist outside of dev? Will need to see how things go.
if (process.env.NODE_ENV === 'development') {
useEffect(() => {
if (!connected && instance) {
instance.connect();
if (!connected && instance && instance.getToken() && instance.getSocketUrl()) {
instance.connect(instance.getSocketUrl()!);
}
}, [ connected ]);
}

View file

@ -1,5 +1,4 @@
import Sockette from 'sockette';
import getWebsocketToken from '@/api/server/getWebsocketToken';
import { EventEmitter } from 'events';
export const SOCKET_EVENTS = [
@ -10,37 +9,54 @@ export const SOCKET_EVENTS = [
];
export class Websocket extends EventEmitter {
private socket: Sockette | null;
private readonly uuid: string;
// The socket instance being tracked.
private socket: Sockette | null = null;
constructor (uuid: string) {
super();
// The URL being connected to for the socket.
private url: string | null = null;
this.socket = null;
this.uuid = uuid;
// The authentication token passed along with every request to the Daemon.
// By default this token expires every 15 minutes and must therefore be
// refreshed at a pretty continuous interval. The socket server will respond
// with "token expiring" and "token expired" events when approaching 3 minutes
// and 0 minutes to expiry.
private token: string = '';
// Connects to the websocket instance and sets the token for the initial request.
connect (url: string) {
this.url = url;
this.socket = new Sockette(url, {
onmessage: e => {
try {
let { event, args } = JSON.parse(e.data);
this.emit(event, ...args);
} catch (ex) {
console.warn('Failed to parse incoming websocket message.', ex);
}
},
onopen: () => this.emit('SOCKET_OPEN'),
onreconnect: () => this.emit('SOCKET_RECONNECT'),
onclose: () => this.emit('SOCKET_CLOSE'),
onerror: () => this.emit('SOCKET_ERROR'),
});
}
async connect (): Promise<void> {
getWebsocketToken(this.uuid)
.then(url => {
this.socket = new Sockette(url, {
onmessage: e => {
try {
let { event, args } = JSON.parse(e.data);
this.emit(event, ...args);
} catch (ex) {
console.warn('Failed to parse incoming websocket message.', ex);
}
},
onopen: () => this.emit('SOCKET_OPEN'),
onreconnect: () => this.emit('SOCKET_RECONNECT'),
onclose: () => this.emit('SOCKET_CLOSE'),
onerror: () => this.emit('SOCKET_ERROR'),
});
// Returns the URL connected to for the socket.
getSocketUrl (): string | null {
return this.url;
}
return Promise.resolve();
})
.catch(error => Promise.reject(error));
// Sets the authentication token to use when sending commands back and forth
// between the websocket instance.
setToken (token: string): this {
this.token = token;
return this;
}
// Returns the token being used at the current moment.
getToken (): string {
return this.token;
}
close (code?: number, reason?: string) {
@ -57,7 +73,9 @@ export class Websocket extends EventEmitter {
send (event: string, payload?: string | string[]) {
this.socket && this.socket.send(JSON.stringify({
event, args: Array.isArray(payload) ? payload : [ payload ],
event,
args: Array.isArray(payload) ? payload : [ payload ],
token: this.token || '',
}));
}
}