Compare commits
54 Commits
Author | SHA1 | Date | |
---|---|---|---|
0ee13b4e06 | |||
21f5882fa3 | |||
48b43f9f0d | |||
d3d476fd53 | |||
b80b8a0a20 | |||
384943f697 | |||
e9239ed978 | |||
baf1844866 | |||
0b3d7f8a06 | |||
c38a2745e9 | |||
a0f39d1c5b | |||
c67ac868a5 | |||
90e1a0453e | |||
d7765fb5dc | |||
0fdd17b430 | |||
0562de6aa1 | |||
7b550a35aa | |||
fb66aac6e7 | |||
208790cfcf | |||
5978bbaf66 | |||
1c47eafe5f | |||
69e3a71354 | |||
21e92bf0c1 | |||
d732e6e7aa | |||
5fdfcdb407 | |||
49e2e90bda | |||
b8e53e7b42 | |||
1136841b3d | |||
42cbc51d22 | |||
2d16403ad1 | |||
afe847499a | |||
f980bb70b4 | |||
f192a8f041 | |||
64bf3aef6d | |||
a5e3cbd05b | |||
2f0fad999a | |||
5e6477720d | |||
bad8bf0688 | |||
4f1db106fb | |||
d47829a8b2 | |||
ca55d06244 | |||
7284924b26 | |||
10857aa12b | |||
c968c7f844 | |||
b07015f6c4 | |||
ca4ddade17 | |||
17eaea4124 | |||
d3d8f6ff57 | |||
906661c7f4 | |||
ea46caebb7 | |||
973e896fbf | |||
4605035b01 | |||
1e4e2c4ab6 | |||
30896b045f |
@ -12,20 +12,12 @@ stages:
|
||||
- release
|
||||
- metadata
|
||||
|
||||
before_script:
|
||||
- npm install -g @shipzone/npmci
|
||||
|
||||
# ====================
|
||||
# security stage
|
||||
# ====================
|
||||
mirror:
|
||||
stage: security
|
||||
script:
|
||||
- npmci git mirror
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
auditProductionDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
@ -36,6 +28,7 @@ auditProductionDependencies:
|
||||
- npmci command npm audit --audit-level=high --only=prod --production
|
||||
tags:
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
auditDevDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
@ -96,10 +89,9 @@ codequality:
|
||||
only:
|
||||
- tags
|
||||
script:
|
||||
- npmci command npm install -g tslint typescript
|
||||
- npmci command npm install -g typescript
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
@ -119,11 +111,10 @@ trigger:
|
||||
pages:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci node install lts
|
||||
- npmci command npm install -g @gitzone/tsdoc
|
||||
- npmci node install stable
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command tsdoc
|
||||
- npmci command npm run buildDocs
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
|
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
@ -2,28 +2,10 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "current file",
|
||||
"type": "node",
|
||||
"command": "npm test",
|
||||
"name": "Run npm test",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"${relativeFile}"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
"name": "test.ts",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"test/test.ts"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
"githost": "gitlab.com",
|
||||
"gitscope": "pushrocks",
|
||||
"gitrepo": "smartproxy",
|
||||
"shortDescription": "a proxy for handling high workloads of proxying",
|
||||
"description": "a proxy for handling high workloads of proxying",
|
||||
"npmPackagename": "@pushrocks/smartproxy",
|
||||
"license": "MIT",
|
||||
"projectDomain": "push.rocks"
|
||||
|
597
package-lock.json
generated
597
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pushrocks/smartproxy",
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.27",
|
||||
"private": false,
|
||||
"description": "a proxy for handling high workloads of proxying",
|
||||
"main": "dist_ts/index.js",
|
||||
@ -11,7 +11,8 @@
|
||||
"scripts": {
|
||||
"test": "(tstest test/)",
|
||||
"build": "(tsbuild --web --allowimplicitany)",
|
||||
"format": "(gitzone format)"
|
||||
"format": "(gitzone format)",
|
||||
"buildDocs": "tsdoc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gitzone/tsbuild": "^2.1.63",
|
||||
@ -21,9 +22,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@pushrocks/lik": "^6.0.0",
|
||||
"@pushrocks/smartnetwork": "^3.0.0",
|
||||
"@pushrocks/smartdelay": "^2.0.13",
|
||||
"@pushrocks/smartpromise": "^3.1.7",
|
||||
"@pushrocks/smartrequest": "^1.1.56",
|
||||
"@pushrocks/smartrequest": "^2.0.6",
|
||||
"@pushrocks/smartstring": "^4.0.2",
|
||||
"@tsclass/tsclass": "^4.0.17",
|
||||
"@types/ws": "^8.5.3",
|
||||
|
@ -5,7 +5,7 @@ let testProxy: smartproxy.NetworkProxy;
|
||||
|
||||
tap.test('first test', async () => {
|
||||
testProxy = new smartproxy.NetworkProxy({
|
||||
port: 3001
|
||||
port: 3001,
|
||||
});
|
||||
expect(testProxy).toBeInstanceOf(smartproxy.NetworkProxy);
|
||||
});
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@pushrocks/smartproxy',
|
||||
version: '3.0.0',
|
||||
version: '3.0.27',
|
||||
description: 'a proxy for handling high workloads of proxying'
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './smartproxy.classes.networkproxy.js'
|
||||
export * from './smartproxy.classes.networkproxy.js';
|
||||
export * from './smartproxy.portproxy.js';
|
||||
export * from './smartproxy.classes.sslredirect.js'
|
@ -6,7 +6,6 @@ export interface INetworkProxyOptions {
|
||||
}
|
||||
|
||||
export class NetworkProxy {
|
||||
|
||||
// INSTANCE
|
||||
public options: INetworkProxyOptions;
|
||||
public proxyConfigs: plugins.tsclass.network.IReverseProxyConfig[] = [];
|
||||
@ -118,10 +117,10 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
`,
|
||||
},
|
||||
async (req, res) => {
|
||||
console.log('got request');
|
||||
const destinationConfig = this.router.routeReq(req);
|
||||
|
||||
// endRequest function
|
||||
/**
|
||||
* endRequest function
|
||||
* can be used to prematurely end a request
|
||||
*/
|
||||
const endRequest = (
|
||||
statusArg: number = 404,
|
||||
messageArg: string = 'This route is not available on this server.',
|
||||
@ -131,6 +130,15 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
res.end(messageArg);
|
||||
};
|
||||
|
||||
console.log(`got request: ${req.headers.host}${plugins.url.parse(req.url).path}`);
|
||||
const destinationConfig = this.router.routeReq(req);
|
||||
|
||||
if (!destinationConfig) {
|
||||
console.log(`${req.headers.host} can't be routed properly. Terminating request.`);
|
||||
endRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
// authentication
|
||||
if (destinationConfig.authentication) {
|
||||
const authInfo = destinationConfig.authentication;
|
||||
@ -185,6 +193,15 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
req.on('end', (data) => {
|
||||
request.end();
|
||||
});
|
||||
req.on('error', () => {
|
||||
request.end();
|
||||
});
|
||||
req.on('close', () => {
|
||||
request.end();
|
||||
});
|
||||
req.on('timeout', () => {
|
||||
request.end();
|
||||
})
|
||||
}
|
||||
);
|
||||
res.statusCode = response.statusCode;
|
||||
@ -201,6 +218,16 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
response.on('end', () => {
|
||||
res.end();
|
||||
});
|
||||
response.on('error', () => {
|
||||
res.end();
|
||||
});
|
||||
response.on('close', () => {
|
||||
res.end();
|
||||
});
|
||||
response.on('timeout', () => {
|
||||
res.end();
|
||||
});
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
@ -208,54 +235,54 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
const wss = new plugins.ws.WebSocketServer({ server: this.httpsServer });
|
||||
wss.on('connection', (ws: plugins.wsDefault) => {
|
||||
console.log('got connection for wsc');
|
||||
const wscConnected = plugins.smartpromise.defer();
|
||||
|
||||
const wsc = new plugins.wsDefault(this.router.routeWs(ws), {
|
||||
headers: {
|
||||
Host: ws.url,
|
||||
},
|
||||
});
|
||||
wsc.on('open', () => {
|
||||
wscConnected.resolve();
|
||||
});
|
||||
let wscConnectedDeferred: plugins.smartpromise.Deferred<plugins.wsDefault>;
|
||||
|
||||
ws.on('message', async (message) => {
|
||||
await wscConnected.promise;
|
||||
if (!wscConnectedDeferred) {
|
||||
wscConnectedDeferred = plugins.smartpromise.defer();
|
||||
const wsc = new plugins.wsDefault(this.router.routeWs(ws), {
|
||||
headers: {
|
||||
Host: ws.url,
|
||||
},
|
||||
});
|
||||
|
||||
wsc.on('open', () => {
|
||||
wscConnectedDeferred.resolve(wsc);
|
||||
});
|
||||
}
|
||||
const wsc = await wscConnectedDeferred.promise;
|
||||
wsc.emit('message', message);
|
||||
});
|
||||
wsc.on('message', (message) => {
|
||||
ws.emit('message', message);
|
||||
});
|
||||
wsc.on('message', (message) => {
|
||||
ws.emit('message', message);
|
||||
});
|
||||
|
||||
// handle closing
|
||||
const cleanUp = () => {
|
||||
ws.close();
|
||||
wsc.close();
|
||||
};
|
||||
|
||||
ws.on('close', (message) => {
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
// handle closing
|
||||
const cleanUp = () => {
|
||||
ws.removeAllListeners();
|
||||
ws.close();
|
||||
ws.terminate();
|
||||
wsc.removeAllListeners();
|
||||
wsc.close();
|
||||
wsc.terminate();
|
||||
};
|
||||
|
||||
ws.on('close', (message) => {
|
||||
cleanUp();
|
||||
});
|
||||
wsc.on('close', (message) => {
|
||||
cleanUp();
|
||||
wsc.on('close', (message) => {
|
||||
cleanUp();
|
||||
});
|
||||
});
|
||||
});
|
||||
this.httpsServer.keepAliveTimeout = 61000;
|
||||
this.httpsServer.headersTimeout = 65000;
|
||||
|
||||
this.httpsServer.on('connection', (connection: plugins.net.Socket) => {
|
||||
connection.setTimeout(120000);
|
||||
this.socketMap.add(connection);
|
||||
console.log(`added connection. now ${this.socketMap.getArray().length} sockets connected.`);
|
||||
const cleanupConnection = () => {
|
||||
if (this.socketMap.checkForObject(connection)) {
|
||||
this.socketMap.remove(connection);
|
||||
connection.end();
|
||||
connection.removeAllListeners();
|
||||
console.log(`removed connection. ${this.socketMap.getArray().length} sockets remaining.`);
|
||||
connection.destroy();
|
||||
console.log(`socket successfully destroyed.`);
|
||||
}
|
||||
};
|
||||
connection.on('close', () => {
|
||||
@ -269,14 +296,17 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
});
|
||||
connection.on('timeout', () => {
|
||||
cleanupConnection();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
this.httpsServer.listen(this.options.port);
|
||||
console.log(`ProxyWorker -> OK: now listening for new connections on port ${this.options.port}`);
|
||||
console.log(
|
||||
`ProxyWorker -> OK: now listening for new connections on port ${this.options.port}`
|
||||
);
|
||||
}
|
||||
|
||||
public async updateProxyConfigs(proxyConfigsArg: plugins.tsclass.network.IReverseProxyConfig[]) {
|
||||
console.log(`got new proxy configs`);
|
||||
this.proxyConfigs = proxyConfigsArg;
|
||||
this.router.setNewProxyConfigs(proxyConfigsArg);
|
||||
for (const hostCandidate of this.proxyConfigs) {
|
||||
@ -303,8 +333,12 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
||||
});
|
||||
this.httpsServer;
|
||||
}
|
||||
/* this.httpsServer.close();
|
||||
this.httpsServer.listen(this.port); */
|
||||
}
|
||||
|
||||
public async addDefaultHeaders(headersArg: { [key: string]: string }) {
|
||||
for (const headerKey of Object.keys(headersArg)) {
|
||||
this.defaultHeaders[headerKey] = headersArg[headerKey];
|
||||
}
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
|
32
ts/smartproxy.classes.sslredirect.ts
Normal file
32
ts/smartproxy.classes.sslredirect.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as plugins from './smartproxy.plugins.js';
|
||||
|
||||
export class SslRedirect {
|
||||
httpServer: plugins.http.Server;
|
||||
port: number;
|
||||
constructor(portArg: number) {
|
||||
this.port = portArg;
|
||||
}
|
||||
|
||||
public async start() {
|
||||
this.httpServer = plugins.http.createServer((request, response) => {
|
||||
const requestUrl = new URL(request.url, `http://${request.headers.host}`);
|
||||
const completeUrlWithoutProtocol = `${requestUrl.host}${requestUrl.pathname}${requestUrl.search}`;
|
||||
const redirectUrl = `https://${completeUrlWithoutProtocol}`;
|
||||
console.log(`Got http request for http://${completeUrlWithoutProtocol}`);
|
||||
console.log(`Redirecting to ${redirectUrl}`);
|
||||
response.writeHead(302, {
|
||||
Location: redirectUrl,
|
||||
});
|
||||
response.end();
|
||||
});
|
||||
this.httpServer.listen(this.port);
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
const done = plugins.smartpromise.defer();
|
||||
this.httpServer.close(() => {
|
||||
done.resolve();
|
||||
});
|
||||
await done.promise;
|
||||
}
|
||||
}
|
@ -13,11 +13,12 @@ export { tsclass };
|
||||
|
||||
// pushrocks scope
|
||||
import * as lik from '@pushrocks/lik';
|
||||
import * as smartdelay from '@pushrocks/smartdelay';
|
||||
import * as smartpromise from '@pushrocks/smartpromise';
|
||||
import * as smartrequest from '@pushrocks/smartrequest';
|
||||
import * as smartstring from '@pushrocks/smartstring';
|
||||
|
||||
export { lik, smartrequest, smartpromise, smartstring };
|
||||
export { lik, smartdelay, smartrequest, smartpromise, smartstring };
|
||||
|
||||
// third party scope
|
||||
import * as ws from 'ws';
|
||||
|
@ -1,30 +1,17 @@
|
||||
import * as plugins from './smartproxy.plugins.js';
|
||||
import * as net from 'net';
|
||||
let netServer: plugins.net.Server;
|
||||
let httpServer: plugins.http.Server;
|
||||
|
||||
export class PortProxy {
|
||||
netServer: plugins.net.Server;
|
||||
fromPort: number;
|
||||
toPort: number;
|
||||
|
||||
constructor(fromPortArg: number, toPortArg: number) {
|
||||
this.fromPort = fromPortArg;
|
||||
this.toPort = toPortArg
|
||||
this.toPort = toPortArg;
|
||||
}
|
||||
|
||||
public async start () {
|
||||
httpServer = plugins.http.createServer((request, response) => {
|
||||
const requestUrl = new URL(request.url, `http://${request.headers.host}`);
|
||||
const completeUrlWithoutProtocol = `${requestUrl.host}${requestUrl.pathname}${requestUrl.search}`;
|
||||
const redirectUrl = `https://${completeUrlWithoutProtocol}`;
|
||||
console.log(`Got http request for http://${completeUrlWithoutProtocol}`);
|
||||
console.log(`Redirecting to ${redirectUrl}`);
|
||||
response.writeHead(302, {
|
||||
Location: redirectUrl,
|
||||
});
|
||||
response.end();
|
||||
});
|
||||
httpServer.listen(this.fromPort);
|
||||
public async start() {
|
||||
const cleanUpSockets = (from: plugins.net.Socket, to: plugins.net.Socket) => {
|
||||
from.end();
|
||||
to.end();
|
||||
@ -34,8 +21,8 @@ export class PortProxy {
|
||||
to.unpipe();
|
||||
from.destroy();
|
||||
to.destroy();
|
||||
}
|
||||
netServer = net
|
||||
};
|
||||
this.netServer = net
|
||||
.createServer((from) => {
|
||||
const to = net.createConnection({
|
||||
host: 'localhost',
|
||||
@ -64,10 +51,10 @@ export class PortProxy {
|
||||
});
|
||||
from.on('end', () => {
|
||||
cleanUpSockets(from, to);
|
||||
})
|
||||
});
|
||||
to.on('end', () => {
|
||||
cleanUpSockets(from, to);
|
||||
})
|
||||
});
|
||||
})
|
||||
.listen(this.fromPort);
|
||||
console.log(`PortProxy -> OK: Now listening on port ${this.fromPort}`);
|
||||
@ -75,11 +62,9 @@ export class PortProxy {
|
||||
|
||||
public async stop() {
|
||||
const done = plugins.smartpromise.defer();
|
||||
httpServer.close(() => {
|
||||
netServer.close(() => {
|
||||
done.resolve();
|
||||
});
|
||||
this.netServer.close(() => {
|
||||
done.resolve();
|
||||
});
|
||||
await done.promise;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user