Compare commits
72 Commits
Author | SHA1 | Date | |
---|---|---|---|
0cc7184e58 | |||
392e241208 | |||
32c6d77178 | |||
2c4316d2d3 | |||
62e6387c1d | |||
7fe22e962a | |||
3f1f718308 | |||
ce94d283c1 | |||
a1c4f3c341 | |||
8087bab197 | |||
db63e7bf79 | |||
2615a0ebd4 | |||
d5d77af98d | |||
1f1bf77807 | |||
d4269d290d | |||
e05e5ede55 | |||
b6c7f13baa | |||
055d328bd0 | |||
20b9a220fc | |||
2170fe3518 | |||
04b13e53b9 | |||
f1a4fae704 | |||
5ee5147606 | |||
748c6e14e4 | |||
f018957de4 | |||
a6583b037c | |||
3ab4144c9a | |||
0d2885ace4 | |||
1723275215 | |||
977d8b0310 | |||
5bb065f82b | |||
942b812f97 | |||
59a025b308 | |||
458e7d6b58 | |||
7b0f824d29 | |||
b5796b86d5 | |||
1f8ea59221 | |||
d717568572 | |||
28d050851f | |||
acbd109985 | |||
cc38a6d10e | |||
748b07efe2 | |||
be4fd0978a | |||
4521010b82 | |||
bd1f1a4c1c | |||
d3bdd56660 | |||
c38a7c4c32 | |||
858628196a | |||
4910679058 | |||
97db2012ca | |||
0ee13b4e06 | |||
21f5882fa3 | |||
48b43f9f0d | |||
d3d476fd53 | |||
b80b8a0a20 | |||
384943f697 | |||
e9239ed978 | |||
baf1844866 | |||
0b3d7f8a06 | |||
c38a2745e9 | |||
a0f39d1c5b | |||
c67ac868a5 | |||
90e1a0453e | |||
d7765fb5dc | |||
0fdd17b430 | |||
0562de6aa1 | |||
7b550a35aa | |||
fb66aac6e7 | |||
208790cfcf | |||
5978bbaf66 | |||
1c47eafe5f | |||
69e3a71354 |
14983
package-lock.json
generated
14983
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pushrocks/smartproxy",
|
"name": "@pushrocks/smartproxy",
|
||||||
"version": "3.0.16",
|
"version": "3.0.52",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "a proxy for handling high workloads of proxying",
|
"description": "a proxy for handling high workloads of proxying",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
@ -15,18 +15,19 @@
|
|||||||
"buildDocs": "tsdoc"
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gitzone/tsbuild": "^2.1.63",
|
"@gitzone/tsbuild": "^2.1.65",
|
||||||
"@gitzone/tstest": "^1.0.72",
|
"@gitzone/tsrun": "^1.2.39",
|
||||||
|
"@gitzone/tstest": "^1.0.73",
|
||||||
"@pushrocks/tapbundle": "^5.0.4",
|
"@pushrocks/tapbundle": "^5.0.4",
|
||||||
"@types/node": "^18.6.2"
|
"@types/node": "^18.7.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pushrocks/lik": "^6.0.0",
|
"@pushrocks/lik": "^6.0.0",
|
||||||
"@pushrocks/smartdelay": "^2.0.13",
|
"@pushrocks/smartdelay": "^2.0.13",
|
||||||
"@pushrocks/smartpromise": "^3.1.7",
|
"@pushrocks/smartpromise": "^3.1.7",
|
||||||
"@pushrocks/smartrequest": "^2.0.5",
|
"@pushrocks/smartrequest": "^2.0.10",
|
||||||
"@pushrocks/smartstring": "^4.0.2",
|
"@pushrocks/smartstring": "^4.0.2",
|
||||||
"@tsclass/tsclass": "^4.0.17",
|
"@tsclass/tsclass": "^4.0.19",
|
||||||
"@types/ws": "^8.5.3",
|
"@types/ws": "^8.5.3",
|
||||||
"ws": "^8.8.1"
|
"ws": "^8.8.1"
|
||||||
},
|
},
|
||||||
|
4341
pnpm-lock.yaml
generated
Normal file
4341
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@pushrocks/smartproxy',
|
name: '@pushrocks/smartproxy',
|
||||||
version: '3.0.16',
|
version: '3.0.52',
|
||||||
description: 'a proxy for handling high workloads of proxying'
|
description: 'a proxy for handling high workloads of proxying'
|
||||||
}
|
}
|
||||||
|
@ -116,26 +116,30 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
|||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
async (req, res) => {
|
async (originRequest, originResponse) => {
|
||||||
/**
|
/**
|
||||||
* endRequest function
|
* endRequest function
|
||||||
* can be used to prematurely end a request
|
* can be used to prematurely end a request
|
||||||
*/
|
*/
|
||||||
const endRequest = (
|
const endOriginReqRes = (
|
||||||
statusArg: number = 404,
|
statusArg: number = 404,
|
||||||
messageArg: string = 'This route is not available on this server.',
|
messageArg: string = 'This route is not available on this server.',
|
||||||
headers: plugins.http.OutgoingHttpHeaders = {}
|
headers: plugins.http.OutgoingHttpHeaders = {}
|
||||||
) => {
|
) => {
|
||||||
res.writeHead(statusArg, messageArg);
|
originResponse.writeHead(statusArg, messageArg);
|
||||||
res.end(messageArg);
|
originResponse.end(messageArg);
|
||||||
|
if (originRequest.socket !== originResponse.socket) {
|
||||||
|
console.log('hey, something is strange.')
|
||||||
|
}
|
||||||
|
originResponse.destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`got request: ${req.headers.host}${plugins.url.parse(req.url).path}`);
|
console.log(`got request: ${originRequest.headers.host}${plugins.url.parse(originRequest.url).path}`);
|
||||||
const destinationConfig = this.router.routeReq(req);
|
const destinationConfig = this.router.routeReq(originRequest);
|
||||||
|
|
||||||
if (!destinationConfig) {
|
if (!destinationConfig) {
|
||||||
console.log(`${req.headers.host} can't be routed properly. Terminating request.`);
|
console.log(`${originRequest.headers.host} can't be routed properly. Terminating request.`);
|
||||||
endRequest();
|
endOriginReqRes();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,14 +148,14 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
|||||||
const authInfo = destinationConfig.authentication;
|
const authInfo = destinationConfig.authentication;
|
||||||
switch (authInfo.type) {
|
switch (authInfo.type) {
|
||||||
case 'Basic':
|
case 'Basic':
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = originRequest.headers.authorization;
|
||||||
if (authHeader) {
|
if (authHeader) {
|
||||||
if (!authHeader.includes('Basic ')) {
|
if (!authHeader.includes('Basic ')) {
|
||||||
return endRequest(401, 'Authentication required', {
|
return endOriginReqRes(401, 'Authentication required', {
|
||||||
'WWW-Authenticate': 'Basic realm="Access to the staging site", charset="UTF-8"',
|
'WWW-Authenticate': 'Basic realm="Access to the staging site", charset="UTF-8"',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const authStringBase64 = req.headers.authorization.replace('Basic ', '');
|
const authStringBase64 = originRequest.headers.authorization.replace('Basic ', '');
|
||||||
const authString: string = plugins.smartstring.base64.decode(authStringBase64);
|
const authString: string = plugins.smartstring.base64.decode(authStringBase64);
|
||||||
const userPassArray = authString.split(':');
|
const userPassArray = authString.split(':');
|
||||||
const user = userPassArray[0];
|
const user = userPassArray[0];
|
||||||
@ -159,12 +163,12 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
|||||||
if (user === authInfo.user && pass === authInfo.pass) {
|
if (user === authInfo.user && pass === authInfo.pass) {
|
||||||
console.log('request successfully authenticated');
|
console.log('request successfully authenticated');
|
||||||
} else {
|
} else {
|
||||||
return endRequest(403, 'Forbidden: Wrong credentials');
|
return endOriginReqRes(403, 'Forbidden: Wrong credentials');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return endRequest(
|
return endOriginReqRes(
|
||||||
403,
|
403,
|
||||||
'Forbidden: unsupported authentication method configured. Please report to the admin.'
|
'Forbidden: unsupported authentication method configured. Please report to the admin.'
|
||||||
);
|
);
|
||||||
@ -173,113 +177,128 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
|||||||
|
|
||||||
let destinationUrl: string;
|
let destinationUrl: string;
|
||||||
if (destinationConfig) {
|
if (destinationConfig) {
|
||||||
destinationUrl = `http://${destinationConfig.destinationIp}:${destinationConfig.destinationPort}${req.url}`;
|
destinationUrl = `http://${destinationConfig.destinationIp}:${destinationConfig.destinationPort}${originRequest.url}`;
|
||||||
} else {
|
} else {
|
||||||
return endRequest();
|
return endOriginReqRes();
|
||||||
}
|
}
|
||||||
console.log(destinationUrl);
|
console.log(destinationUrl);
|
||||||
const response = await plugins.smartrequest.request(
|
const proxyResponse = await plugins.smartrequest.request(
|
||||||
destinationUrl,
|
destinationUrl,
|
||||||
{
|
{
|
||||||
method: req.method,
|
method: originRequest.method,
|
||||||
headers: req.headers,
|
headers: {
|
||||||
|
...originRequest.headers,
|
||||||
|
'X-Forwarded-Host': originRequest.headers.host,
|
||||||
|
'X-Forwarded-Proto': 'https'
|
||||||
|
},
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
},
|
},
|
||||||
true, // lets make this streaming
|
true, // lets make this streaming
|
||||||
(request) => {
|
(proxyRequest) => {
|
||||||
req.on('data', (data) => {
|
originRequest.on('data', (data) => {
|
||||||
request.write(data);
|
proxyRequest.write(data);
|
||||||
});
|
});
|
||||||
req.on('end', (data) => {
|
originRequest.on('end', (data) => {
|
||||||
request.end();
|
proxyRequest.end();
|
||||||
});
|
});
|
||||||
|
originRequest.on('error', () => {
|
||||||
|
proxyRequest.end();
|
||||||
|
});
|
||||||
|
originRequest.on('close', () => {
|
||||||
|
proxyRequest.end();
|
||||||
|
});
|
||||||
|
originRequest.on('timeout', () => {
|
||||||
|
proxyRequest.end();
|
||||||
|
originRequest.destroy();
|
||||||
|
});
|
||||||
|
proxyRequest.on('error', () => {
|
||||||
|
endOriginReqRes();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
res.statusCode = response.statusCode;
|
originResponse.statusCode = proxyResponse.statusCode;
|
||||||
console.log(response.statusCode);
|
console.log(proxyResponse.statusCode);
|
||||||
for (const defaultHeader of Object.keys(this.defaultHeaders)) {
|
for (const defaultHeader of Object.keys(this.defaultHeaders)) {
|
||||||
res.setHeader(defaultHeader, this.defaultHeaders[defaultHeader]);
|
originResponse.setHeader(defaultHeader, this.defaultHeaders[defaultHeader]);
|
||||||
}
|
}
|
||||||
for (const header of Object.keys(response.headers)) {
|
for (const header of Object.keys(proxyResponse.headers)) {
|
||||||
res.setHeader(header, response.headers[header]);
|
originResponse.setHeader(header, proxyResponse.headers[header]);
|
||||||
}
|
}
|
||||||
response.on('data', (data) => {
|
proxyResponse.on('data', (data) => {
|
||||||
res.write(data);
|
originResponse.write(data);
|
||||||
});
|
});
|
||||||
response.on('end', () => {
|
proxyResponse.on('end', () => {
|
||||||
res.end();
|
originResponse.end();
|
||||||
});
|
});
|
||||||
|
proxyResponse.on('error', () => {
|
||||||
|
originResponse.destroy();
|
||||||
|
});
|
||||||
|
proxyResponse.on('close', () => {
|
||||||
|
originResponse.end();
|
||||||
|
});
|
||||||
|
proxyResponse.on('timeout', () => {
|
||||||
|
originResponse.end();
|
||||||
|
originResponse.destroy()
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Enable websockets
|
// Enable websockets
|
||||||
const wss = new plugins.ws.WebSocketServer({ server: this.httpsServer });
|
const wss = new plugins.ws.WebSocketServer({ server: this.httpsServer });
|
||||||
wss.on('connection', (ws: plugins.wsDefault) => {
|
wss.on('connection', (ws: plugins.wsDefault, reqArg: plugins.http.IncomingMessage) => {
|
||||||
console.log('got connection for wsc');
|
console.log(`wss: got connection for wsc for https://${reqArg.headers.host}${reqArg.url}`);
|
||||||
const wscConnected = plugins.smartpromise.defer();
|
let wscConnectedDeferred: plugins.smartpromise.Deferred<plugins.wsDefault>;
|
||||||
|
|
||||||
const wsc = new plugins.wsDefault(this.router.routeWs(ws), {
|
|
||||||
headers: {
|
|
||||||
Host: ws.url,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
wsc.on('open', () => {
|
|
||||||
wscConnected.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.on('message', async (message) => {
|
ws.on('message', async (message) => {
|
||||||
await wscConnected.promise;
|
if (!wscConnectedDeferred) {
|
||||||
wsc.emit('message', message);
|
wscConnectedDeferred = plugins.smartpromise.defer();
|
||||||
|
let wsc: plugins.wsDefault;
|
||||||
|
try {
|
||||||
|
wsc = new plugins.wsDefault(`ws://${this.router.routeReq(reqArg).destinationIp}:${this.router.routeReq(reqArg).destinationPort}${reqArg.url}`, {
|
||||||
|
headers: reqArg.headers
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
ws.terminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wsc.on('open', () => {
|
||||||
|
console.log('wsc opened.');
|
||||||
|
wscConnectedDeferred.resolve(wsc);
|
||||||
});
|
});
|
||||||
wsc.on('message', (message) => {
|
wsc.on('message', (message) => {
|
||||||
ws.emit('message', message);
|
ws.send(message);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
const wsc = await wscConnectedDeferred.promise;
|
||||||
|
wsc.send(message);
|
||||||
// handle closing
|
// handle closing
|
||||||
const cleanUp = () => {
|
const cleanUp = () => {
|
||||||
ws.removeAllListeners();
|
|
||||||
ws.close();
|
|
||||||
ws.terminate();
|
ws.terminate();
|
||||||
wsc.removeAllListeners();
|
|
||||||
wsc.close();
|
|
||||||
wsc.terminate();
|
wsc.terminate();
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.on('close', (message) => {
|
ws.on('close', (message) => {
|
||||||
cleanUp();
|
cleanUp();
|
||||||
});
|
});
|
||||||
|
|
||||||
wsc.on('close', (message) => {
|
wsc.on('close', (message) => {
|
||||||
cleanUp();
|
cleanUp();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.httpsServer.keepAliveTimeout = 61000;
|
});
|
||||||
this.httpsServer.headersTimeout = 65000;
|
this.httpsServer.keepAliveTimeout = 600 * 1000;
|
||||||
|
this.httpsServer.headersTimeout = 600 * 1000;
|
||||||
|
|
||||||
this.httpsServer.on('connection', (connection: plugins.net.Socket) => {
|
this.httpsServer.on('connection', (connection: plugins.net.Socket) => {
|
||||||
connection.setTimeout(10000);
|
|
||||||
let destroyed = false;
|
|
||||||
this.socketMap.add(connection);
|
this.socketMap.add(connection);
|
||||||
console.log(`added connection. now ${this.socketMap.getArray().length} sockets connected.`);
|
console.log(`added connection. now ${this.socketMap.getArray().length} sockets connected.`);
|
||||||
const destroyConnection = () => {
|
|
||||||
if (!destroyed) {
|
|
||||||
destroyed = true;
|
|
||||||
connection.destroy();
|
|
||||||
console.log(`socket successfully destroyed.`);
|
|
||||||
plugins.smartdelay.delayFor(1000).then(() => {
|
|
||||||
connection.removeAllListeners();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const cleanupConnection = () => {
|
const cleanupConnection = () => {
|
||||||
if (this.socketMap.checkForObject(connection)) {
|
if (this.socketMap.checkForObject(connection)) {
|
||||||
this.socketMap.remove(connection);
|
this.socketMap.remove(connection);
|
||||||
plugins.smartdelay.delayFor(200).then(() => {
|
|
||||||
destroyConnection();
|
|
||||||
});
|
|
||||||
console.log(`removed connection. ${this.socketMap.getArray().length} sockets remaining.`);
|
console.log(`removed connection. ${this.socketMap.getArray().length} sockets remaining.`);
|
||||||
connection.end(() => {
|
connection.destroy();
|
||||||
destroyConnection();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
connection.on('close', () => {
|
connection.on('close', () => {
|
||||||
@ -293,12 +312,12 @@ JNj2Dr5H0XoLFFnvuvzcRbhlJ9J67JzR+7g=
|
|||||||
});
|
});
|
||||||
connection.on('timeout', () => {
|
connection.on('timeout', () => {
|
||||||
cleanupConnection();
|
cleanupConnection();
|
||||||
});
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
this.httpsServer.listen(this.options.port);
|
this.httpsServer.listen(this.options.port);
|
||||||
console.log(
|
console.log(
|
||||||
`ProxyWorker -> OK: now listening for new connections on port ${this.options.port}`
|
`NetworkProxy -> OK: now listening for new connections on port ${this.options.port}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,12 +21,4 @@ export class ProxyRouter {
|
|||||||
});
|
});
|
||||||
return correspodingReverseProxyConfig;
|
return correspodingReverseProxyConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public routeWs(ws: plugins.wsDefault) {
|
|
||||||
const originalHost = plugins.url.parse(ws.url).host;
|
|
||||||
const correspodingReverseProxyConfig = this.reverseProxyConfigs.find((reverseConfig) => {
|
|
||||||
return reverseConfig.hostName === originalHost;
|
|
||||||
});
|
|
||||||
return correspodingReverseProxyConfig.destinationIp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user