ws-rmi
Version:
A Remote Method Invocation implementation written in JavaScript utilising the WebSocket protocol
63 lines (62 loc) • 2.81 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.exposeFunctions = exports.handleRequest = void 0;
const RMIRequest_1 = require("./types/RMIRequest");
const RMIRemoteResult_1 = require("./types/RMIRemoteResult");
const RMIRemoteError_1 = require("./types/RMIRemoteError");
/**
* Handles an {@link RMIRequest} and produces either an {@link RMIRemoteResult} if the specified target:
* 1. Exists
* 2. Is a function
* 3. Doesn't throw an Error
*
* Otherwise, an {@link RMIRemoteError} is produced detailing that an error occurred. For security purposes, a generic
* error message is generated. If an Error is thrown, it is propagated back to {@link exposeFunctions} where a given
* error handler can handle it further (e.g. console logs, output to a log file, etc.)
*
* @param rmi The request body
* @param functions A class / object containing functions that can be invoked.
*/
const handleRequest = async ({ rmi }, functions) => {
const { data, id } = rmi;
const { target, args } = data;
const functionToInvoke = functions[target];
if (typeof functionToInvoke !== "function")
return (0, RMIRemoteError_1.createRMIRemoteError)(id, `Target "${target}" is not invokable!`);
const result = await functionToInvoke(...args);
return (0, RMIRemoteResult_1.createRMIRemoteResult)(id, result);
};
exports.handleRequest = handleRequest;
const exposeFunctions = ({ ws, config: { logger: log } }, functions) => {
ws.addEventListener("message", async ({ data }) => {
log.debug(`Client sent "${data}"`);
let request;
try {
request = JSON.parse(data);
}
catch (e) {
log.debug(`Error parsing "${data}"; Cause:\n${e}`);
return;
}
log.debug("Data is valid JSON. Validating as RMI Request...");
if (!(0, RMIRequest_1.validateRMIRequest)(request)) {
log.debug(`Request was invalid! Request was\n${request}`);
return;
}
if (request.rmi.type !== "REQUEST")
return;
let response;
try {
log.info("Client sent a valid RMI Request. Attempting to invoke function...");
response = await (0, exports.handleRequest)(request, functions);
}
catch (e) {
log.info(`There was an error during invocation of a function. Request was:\n${request}\nError was:\n${e}`);
response = (0, RMIRemoteError_1.createRMIRemoteError)(request.rmi.id, "An unexpected error occurred during invocation.");
}
const responseString = JSON.stringify(response);
log.info(`Request handled; Sending the following back to client:\n${responseString}`);
ws.send(responseString);
});
};
exports.exposeFunctions = exposeFunctions;