cassata
Version:
A package, to proxy the server to your current location
250 lines (221 loc) • 8.04 kB
JavaScript
const http = require("http");
const express = require('express');
const router = express.Router();
const path = require('path');
const proxySettings = {
roomId: 12345,
password: "admin",
}
let io;
let isRoom = false;
let isClosed = false;
let finalResult = {};
let newServer;
let isCredentials = false;
let socketId;
let originSocket;
function isProxyConnected() {
return isRoom;
}
async function init() {
// Setting the data to the final Data to send the data to the server.
io.use((socket, next) => {
// Setting the data in proxy success
socket.on("ProxyDataSuccess", data => {
if (!isClosed && isCredentials) {
finalResult = { success: true, data }
}
})
// Setting the data on proxy failure
socket.on("ProxyError", data => {
if (!isClosed && isCredentials) {
finalResult = { success: false, data }
}
})
next()
});
io.on("connection", (socket) => {
// Creating a new proxyserver
socket.on('CreateProxy', (room) => {
if (proxySettings.roomId.toString() === room.roomId.toString() && room.password == proxySettings.password && !isRoom) {
if (!socketId) {
socketId = room.socketid
originSocket = socket
// Configuring the socket.id to make sure we only persist one session
socket["id"] = socketId
console.log('\x1b[32m%s\x1b[0m', "proxy:server >> Proxy server has been connected and configured");
// socket.join()
isRoom = true;
isClosed = false;
isCredentials = true;
socket.emit("AuthSuccess", socketId)
}
}
if (!isCredentials) {
sendAuthFailure()
}
})
// override the connection state, so no further requests are made.
socket.on("override", (id) => {
if (isCredentials && id == socketId) {
console.log("\x1b[33m%s\x1b[0m", "proxy:server >> Overriding session")
isClosed = true;
isCredentials = false;
isRoom = false;
socketId = undefined;
finalResult = {};
} else {
sendAuthFailure()
}
})
// On the exit conditions for proxy disconnect
socket.on("disconnect", () => {
if (socket["id"] == socketId) {
console.log("\x1b[33m%s\x1b[0m", "proxy:server >> Disconnecting the origin socket")
isClosed = true;
isCredentials = false;
isRoom = false;
finalResult = {};
isRoom = false;
socketId = undefined;
originSocket = null;
}
})
});
}
/**
* ### This function handles the array of urls passed to the function
* @param {Array<String>} arr
* @param {Number=8000} timeout
* @param {Number=0} index
* @param {Array} result
* @returns
*/
function handleArrays(arr, timeout = 8000, index = 0, result = []) {
return new Promise((resolve, reject) => {
(async () => {
try {
// console.log(arr[index])
// console.log(index)
if (index >= arr.length) {
resolve(result)
}
if (typeof (arr[index]) !== "string") {
throw Error("\x1b[31mproxy:server >> The data type is not supported\x1b[0m")
}
let dt = await getProxiedData(arr[index], timeout)
result.push(dt)
resolve(await handleArrays(arr, timeout, index + 1, result))
} catch (error) {
reject(error)
}
})()
})
}
/**
* ### perform get request using the proxied server.
* @param {String} url the url you need to search for [Make sure the data returned is in form of JSON]
* @param {number} timeout the default timeout will be ***8000ms***
* @returns {Promise<JSON>} returns a promise of JSON from the request
*/
function getProxiedData(url, timeout = 8000) {
try {
finalResult = {}
return new Promise(async (resolve, reject) => {
if (!typeof (url) === "string" && !Array.isArray(url)) {
console.log("\x1b[31m%s\x1b[0m", "\nproxy:server >> The Expected data type is either String or Array of strings")
reject("The data type required is either String or Array of Strings")
return
}
if (!isProxyConnected()) {
console.log("\x1b[31m%s\x1b[0m", "\nproxy:server >> Use the method isProxyconnected() to check if the proxy client is connected")
reject("Proxy server is not connected")
return
}
if (Array.isArray(url)) {
try {
let resultArr = await handleArrays(url, timeout);
resolve(resultArr)
} catch (error) {
reject(error)
}
} else {
if (!isClosed && isCredentials && socketId) {
originSocket.emit("getProxyData", { url, socketId })
} else {
sendAuthFailure();
}
// Checking data on regular intervals
let msTimeout = 0;
const interval = setInterval(() => {
if (msTimeout >= timeout) {
clearInterval(interval)
reject(`The proxy server did not respond within ${timeout} ms`)
return
}
// on data success
if (finalResult.success) {
clearInterval(interval)
resolve(finalResult)
}
// on data failure
if (finalResult.success == false) {
clearInterval(interval)
reject(finalResult)
return
}
// to watch the time
msTimeout += 5;
}, 5);
}
})
} catch (error) {
return (error.message)
}
}
/**
* ### used to send Auth failure message to the proxy-client
*/
function sendAuthFailure() {
if (!socketId) {
io.emit("AuthFailure");
}
}
/**
* Loading the front-end for the authentication
*/
router.get("/proxyrouter", async (req, res) => {
res.sendFile(path.resolve(__dirname, 'build', 'index.html'))
})
/**
* ### Takes an express server, and returns a proxy server, use the proxy server in return to listen to the data
* @param {Express} server Provide the server created using express.
* @returns {http.Server} Returns a proxied server,
* @note use this server and listen to the ports
* @example "Github link"
*/
function createProxy(server) {
try {
server.use(router)
server.use("/proxydata", express.static(path.resolve(__dirname, 'build')))
newServer = http.createServer(server);
io = require('socket.io')(newServer, {
cors: { origin: '*' },
});
// initializing the socket
init();
return newServer;
} catch (error) {
console.log("\x1b[31m%s\x1b[0m", `proxy:server >> ${error.message}`)
return false;
}
}
/**
* Main exports
*/
module.exports = {
createProxy,
getProxiedData,
isProxyConnected,
proxySettings,
}