Add http tunnel client implements
This commit is contained in:
parent
c68968022e
commit
1c5468bbe8
132
.gitignore
vendored
132
.gitignore
vendored
@ -1,132 +1,2 @@
|
|||||||
# ---> Node
|
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
npm-debug.log
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
web_modules/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variable files
|
|
||||||
.env
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
.parcel-cache
|
|
||||||
|
|
||||||
# Next.js build output
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
|
||||||
.nuxt
|
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
|
||||||
.cache/
|
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
|
||||||
.temp
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
.docusaurus
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
|
||||||
.vscode-test
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
||||||
|
|
@ -1,2 +1,6 @@
|
|||||||
# http-tunnel-client
|
# HTTP Tunnel Client
|
||||||
|
A lightweight http tunnel client using nodejs.
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
- Original [web-tunnel](https://github.com/web-tunnel/lite-http-tunnel-client)
|
||||||
|
- Sambo Chea <sombochea@cubetiqs.com>
|
3
bin/http-tunnel
Normal file
3
bin/http-tunnel
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
require('../client');
|
179
client.js
Normal file
179
client.js
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
const os = require("os");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const http = require("http");
|
||||||
|
const { io } = require("socket.io-client");
|
||||||
|
const HttpsProxyAgent = require("https-proxy-agent");
|
||||||
|
const { program, InvalidArgumentError, Argument } = require("commander");
|
||||||
|
const { TunnelRequest, TunnelResponse } = require("./lib");
|
||||||
|
|
||||||
|
let socket = null;
|
||||||
|
|
||||||
|
function keepAlive() {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (socket && socket.connected) {
|
||||||
|
socket.send("ping");
|
||||||
|
}
|
||||||
|
keepAlive();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initClient(options) {
|
||||||
|
const initParams = {
|
||||||
|
path: "/$web_tunnel",
|
||||||
|
transports: ["websocket"],
|
||||||
|
auth: {
|
||||||
|
token: options.token,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const http_proxy = process.env.https_proxy || process.env.http_proxy;
|
||||||
|
if (http_proxy) {
|
||||||
|
initParams.agent = new HttpsProxyAgent(http_proxy);
|
||||||
|
}
|
||||||
|
socket = io(options.server, initParams);
|
||||||
|
|
||||||
|
socket.on("connect", () => {
|
||||||
|
if (socket.connected) {
|
||||||
|
console.log("client connect to server successfully");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("connect_error", (e) => {
|
||||||
|
console.log("connect error", e && e.message);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("disconnect", () => {
|
||||||
|
console.log("client disconnected");
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("request", (requestId, request) => {
|
||||||
|
const isWebSocket = request.headers.upgrade === "websocket";
|
||||||
|
console.log(`${isWebSocket ? "WS" : request.method}: `, request.path);
|
||||||
|
request.port = options.port;
|
||||||
|
request.hostname = options.host;
|
||||||
|
if (options.origin) {
|
||||||
|
request.headers.host = options.origin;
|
||||||
|
}
|
||||||
|
const tunnelRequest = new TunnelRequest({
|
||||||
|
requestId,
|
||||||
|
socket: socket,
|
||||||
|
});
|
||||||
|
const localReq = http.request(request);
|
||||||
|
tunnelRequest.pipe(localReq);
|
||||||
|
const onTunnelRequestError = (e) => {
|
||||||
|
tunnelRequest.off("end", onTunnelRequestEnd);
|
||||||
|
localReq.destroy(e);
|
||||||
|
};
|
||||||
|
const onTunnelRequestEnd = () => {
|
||||||
|
tunnelRequest.off("error", onTunnelRequestError);
|
||||||
|
};
|
||||||
|
tunnelRequest.once("error", onTunnelRequestError);
|
||||||
|
tunnelRequest.once("end", onTunnelRequestEnd);
|
||||||
|
const onLocalResponse = (localRes) => {
|
||||||
|
localReq.off("error", onLocalError);
|
||||||
|
if (isWebSocket && localRes.upgrade) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tunnelResponse = new TunnelResponse({
|
||||||
|
responseId: requestId,
|
||||||
|
socket: socket,
|
||||||
|
});
|
||||||
|
tunnelResponse.writeHead(
|
||||||
|
localRes.statusCode,
|
||||||
|
localRes.statusMessage,
|
||||||
|
localRes.headers,
|
||||||
|
localRes.httpVersion
|
||||||
|
);
|
||||||
|
localRes.pipe(tunnelResponse);
|
||||||
|
};
|
||||||
|
const onLocalError = (error) => {
|
||||||
|
console.log(error);
|
||||||
|
localReq.off("response", onLocalResponse);
|
||||||
|
socket.emit("request-error", requestId, error && error.message);
|
||||||
|
tunnelRequest.destroy(error);
|
||||||
|
};
|
||||||
|
const onUpgrade = (localRes, localSocket, localHead) => {
|
||||||
|
// localSocket.once('error', onTunnelRequestError);
|
||||||
|
if (localHead && localHead.length) localSocket.unshift(localHead);
|
||||||
|
const tunnelResponse = new TunnelResponse({
|
||||||
|
responseId: requestId,
|
||||||
|
socket: socket,
|
||||||
|
duplex: true,
|
||||||
|
});
|
||||||
|
tunnelResponse.writeHead(null, null, localRes.headers);
|
||||||
|
localSocket.pipe(tunnelResponse).pipe(localSocket);
|
||||||
|
};
|
||||||
|
localReq.once("error", onLocalError);
|
||||||
|
localReq.once("response", onLocalResponse);
|
||||||
|
|
||||||
|
if (isWebSocket) {
|
||||||
|
localReq.on("upgrade", onUpgrade);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
keepAlive();
|
||||||
|
}
|
||||||
|
|
||||||
|
program.name("http-tunnel").description("HTTP tunnel client");
|
||||||
|
|
||||||
|
program
|
||||||
|
.command("start")
|
||||||
|
.argument("<port>", "local server port number", (value) => {
|
||||||
|
const port = parseInt(value, 10);
|
||||||
|
if (isNaN(port)) {
|
||||||
|
throw new InvalidArgumentError("Not a number.");
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
})
|
||||||
|
.option("-p, --profile <string>", "setting profile name", "config")
|
||||||
|
.option("-h, --host <string>", "local host value", "localhost")
|
||||||
|
.option("-o, --origin <string>", "change request origin")
|
||||||
|
.action((port, options) => {
|
||||||
|
const configDir = path.resolve(os.homedir(), ".http-tunnel");
|
||||||
|
if (!fs.existsSync(configDir)) {
|
||||||
|
fs.mkdirSync(configDir);
|
||||||
|
}
|
||||||
|
let config = {};
|
||||||
|
const configFilePath = path.resolve(configDir, `${options.profile}.json`);
|
||||||
|
if (fs.existsSync(configFilePath)) {
|
||||||
|
config = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
|
||||||
|
}
|
||||||
|
if (!config.server) {
|
||||||
|
console.log("Please set remote tunnel server firstly");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!config.token) {
|
||||||
|
console.log(`Please set jwt token for ${config.server} firstly`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
options.port = port;
|
||||||
|
options.token = config.token;
|
||||||
|
options.server = config.server;
|
||||||
|
initClient(options);
|
||||||
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command("config")
|
||||||
|
.addArgument(new Argument("<type>", "config type").choices(["jwt", "server"]))
|
||||||
|
.argument("<value>", "config value")
|
||||||
|
.option("-p --profile <string>", "setting profile name", "config")
|
||||||
|
.action((type, value, options) => {
|
||||||
|
const configDir = path.resolve(os.homedir(), ".http-tunnel");
|
||||||
|
if (!fs.existsSync(configDir)) {
|
||||||
|
fs.mkdirSync(configDir);
|
||||||
|
}
|
||||||
|
let config = {};
|
||||||
|
const configFilePath = path.resolve(configDir, `${options.profile}.json`);
|
||||||
|
if (fs.existsSync(configFilePath)) {
|
||||||
|
config = JSON.parse(fs.readFileSync(configFilePath, "utf8"));
|
||||||
|
}
|
||||||
|
if (type === "jwt") {
|
||||||
|
config.token = value;
|
||||||
|
}
|
||||||
|
if (type === "server") {
|
||||||
|
config.server = value;
|
||||||
|
}
|
||||||
|
fs.writeFileSync(configFilePath, JSON.stringify(config, null, 2));
|
||||||
|
console.log(`${type} config saved successfully`);
|
||||||
|
});
|
||||||
|
|
||||||
|
program.parse();
|
146
lib.js
Normal file
146
lib.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
const stream = require("stream");
|
||||||
|
|
||||||
|
class TunnelRequest extends stream.Readable {
|
||||||
|
constructor({ socket, requestId }) {
|
||||||
|
super();
|
||||||
|
this._socket = socket;
|
||||||
|
this._requestId = requestId;
|
||||||
|
const onRequestPipe = (requestId, data) => {
|
||||||
|
if (this._requestId === requestId) {
|
||||||
|
this.push(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onRequestPipes = (requestId, data) => {
|
||||||
|
if (this._requestId === requestId) {
|
||||||
|
data.forEach((chunk) => {
|
||||||
|
this.push(chunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onRequestPipeError = (requestId, error) => {
|
||||||
|
if (this._requestId === requestId) {
|
||||||
|
this._socket.off("request-pipe", onRequestPipe);
|
||||||
|
this._socket.off("request-pipes", onRequestPipes);
|
||||||
|
this._socket.off("request-pipe-error", onRequestPipeError);
|
||||||
|
this._socket.off("request-pipe-end", onRequestPipeEnd);
|
||||||
|
this.destroy(new Error(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onRequestPipeEnd = (requestId, data) => {
|
||||||
|
if (this._requestId === requestId) {
|
||||||
|
this._socket.off("request-pipe", onRequestPipe);
|
||||||
|
this._socket.off("request-pipes", onRequestPipes);
|
||||||
|
this._socket.off("request-pipe-error", onRequestPipeError);
|
||||||
|
this._socket.off("request-pipe-end", onRequestPipeEnd);
|
||||||
|
if (data) {
|
||||||
|
this.push(data);
|
||||||
|
}
|
||||||
|
this.push(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._socket.on("request-pipe", onRequestPipe);
|
||||||
|
this._socket.on("request-pipes", onRequestPipes);
|
||||||
|
this._socket.on("request-pipe-error", onRequestPipeError);
|
||||||
|
this._socket.on("request-pipe-end", onRequestPipeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
_read() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TunnelResponse extends stream.Duplex {
|
||||||
|
constructor({ socket, responseId, duplex }) {
|
||||||
|
super();
|
||||||
|
this._socket = socket;
|
||||||
|
this._responseId = responseId;
|
||||||
|
if (duplex) {
|
||||||
|
// for websocket request: bidirection
|
||||||
|
const onResponsePipe = (responseId, data) => {
|
||||||
|
if (this._responseId === responseId) {
|
||||||
|
this.push(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onResponsePipes = (responseId, data) => {
|
||||||
|
if (this._responseId === responseId) {
|
||||||
|
data.forEach((chunk) => {
|
||||||
|
this.push(chunk);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onResponsePipeError = (responseId, error) => {
|
||||||
|
if (this._responseId === responseId) {
|
||||||
|
this._socket.off("response-pipe", onResponsePipe);
|
||||||
|
this._socket.off("response-pipes", onResponsePipes);
|
||||||
|
this._socket.off("response-pipe-error", onResponsePipeError);
|
||||||
|
this._socket.off("response-pipe-end", onResponsePipeEnd);
|
||||||
|
this.destroy(new Error(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onResponsePipeEnd = (responseId, data) => {
|
||||||
|
if (this._responseId === responseId) {
|
||||||
|
this._socket.off("response-pipe", onResponsePipe);
|
||||||
|
this._socket.off("response-pipes", onResponsePipes);
|
||||||
|
this._socket.off("response-pipe-error", onResponsePipeError);
|
||||||
|
this._socket.off("response-pipe-end", onResponsePipeEnd);
|
||||||
|
if (data) {
|
||||||
|
this.push(data);
|
||||||
|
}
|
||||||
|
this.push(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._socket.on("response-pipe", onResponsePipe);
|
||||||
|
this._socket.on("response-pipes", onResponsePipes);
|
||||||
|
this._socket.on("response-pipe-error", onResponsePipeError);
|
||||||
|
this._socket.on("response-pipe-end", onResponsePipeEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_write(chunk, encoding, callback) {
|
||||||
|
this._socket.emit("response-pipe", this._responseId, chunk);
|
||||||
|
this._socket.io.engine.once("drain", () => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_writev(chunks, callback) {
|
||||||
|
this._socket.emit("response-pipes", this._responseId, chunks);
|
||||||
|
this._socket.io.engine.once("drain", () => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_final(callback) {
|
||||||
|
this._socket.emit("response-pipe-end", this._responseId);
|
||||||
|
this._socket.io.engine.once("drain", () => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_destroy(e, callback) {
|
||||||
|
if (e) {
|
||||||
|
this._socket.emit(
|
||||||
|
"response-pipe-error",
|
||||||
|
this._responseId,
|
||||||
|
e && e.message
|
||||||
|
);
|
||||||
|
this._socket.io.engine.once("drain", () => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
writeHead(statusCode, statusMessage, headers, httpVersion) {
|
||||||
|
this._socket.emit("response", this._responseId, {
|
||||||
|
statusCode,
|
||||||
|
statusMessage,
|
||||||
|
headers,
|
||||||
|
httpVersion,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_read(size) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.TunnelRequest = TunnelRequest;
|
||||||
|
exports.TunnelResponse = TunnelResponse;
|
239
package-lock.json
generated
Normal file
239
package-lock.json
generated
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
{
|
||||||
|
"name": "@cubetiq/http-tunnel-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "@cubetiq/http-tunnel-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^9.3.0",
|
||||||
|
"https-proxy-agent": "^5.0.1",
|
||||||
|
"socket.io-client": "^4.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||||
|
},
|
||||||
|
"node_modules/agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "9.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
|
||||||
|
"integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || >=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io-client": {
|
||||||
|
"version": "6.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz",
|
||||||
|
"integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.0.3",
|
||||||
|
"ws": "~8.2.3",
|
||||||
|
"xmlhttprequest-ssl": "~2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/engine.io-parser": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||||
|
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/https-proxy-agent": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
|
"node_modules/socket.io-client": {
|
||||||
|
"version": "4.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
|
||||||
|
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io-client": "~6.2.1",
|
||||||
|
"socket.io-parser": "~4.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/socket.io-parser": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==",
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||||
|
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xmlhttprequest-ssl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||||
|
},
|
||||||
|
"agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commander": {
|
||||||
|
"version": "9.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
|
||||||
|
"integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-client": {
|
||||||
|
"version": "6.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz",
|
||||||
|
"integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.0.3",
|
||||||
|
"ws": "~8.2.3",
|
||||||
|
"xmlhttprequest-ssl": "~2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-parser": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz",
|
||||||
|
"integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg=="
|
||||||
|
},
|
||||||
|
"https-proxy-agent": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
|
"socket.io-client": {
|
||||||
|
"version": "4.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
|
||||||
|
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io-client": "~6.2.1",
|
||||||
|
"socket.io-parser": "~4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-parser": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "8.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||||
|
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"xmlhttprequest-ssl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
package.json
Normal file
26
package.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "@cubetiq/http-tunnel-client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A lightweight http tunnel client",
|
||||||
|
"main": "client.js",
|
||||||
|
"bin": {
|
||||||
|
"http-tunnel": "bin/http-tunnel"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "node client.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.cubetiqs.com/cubetiq/http-tunnel-client.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"http-tunnel-client"
|
||||||
|
],
|
||||||
|
"author": "Sambo Chea <sombochea@cubetiqs.com>",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^9.3.0",
|
||||||
|
"https-proxy-agent": "^5.0.1",
|
||||||
|
"socket.io-client": "^4.5.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user