2023-07-27 16:27:50 +02:00
|
|
|
import { expect, tap } from '@push.rocks/tapbundle';
|
2022-07-29 00:49:46 +02:00
|
|
|
import * as smartproxy from '../ts/index.js';
|
2025-02-03 23:41:13 +01:00
|
|
|
import { testCertificates } from './helpers/certificates.js';
|
|
|
|
import * as https from 'https';
|
|
|
|
import * as http from 'http';
|
|
|
|
import { WebSocket, WebSocketServer } from 'ws';
|
2019-08-20 17:50:17 +02:00
|
|
|
|
2022-07-29 00:49:46 +02:00
|
|
|
let testProxy: smartproxy.NetworkProxy;
|
2025-02-03 23:41:13 +01:00
|
|
|
let testServer: http.Server;
|
|
|
|
let wsServer: WebSocketServer;
|
2019-08-21 23:41:06 +02:00
|
|
|
|
2025-02-03 23:41:13 +01:00
|
|
|
// Helper function to make HTTPS requests
|
|
|
|
async function makeHttpsRequest(
|
|
|
|
options: https.RequestOptions,
|
|
|
|
): Promise<{ statusCode: number; headers: http.IncomingHttpHeaders; body: string }> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const req = https.request(options, (res) => {
|
|
|
|
let data = '';
|
|
|
|
res.on('data', (chunk) => (data += chunk));
|
|
|
|
res.on('end', () =>
|
|
|
|
resolve({
|
|
|
|
statusCode: res.statusCode!,
|
|
|
|
headers: res.headers,
|
|
|
|
body: data,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
});
|
|
|
|
req.on('error', reject);
|
|
|
|
req.end();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setup test environment
|
|
|
|
tap.test('setup test environment', async () => {
|
|
|
|
// Create a test HTTP server
|
|
|
|
testServer = http.createServer((req, res) => {
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
|
|
res.end('Hello from test server!');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create a WebSocket server
|
|
|
|
wsServer = new WebSocketServer({ noServer: true });
|
|
|
|
wsServer.on('connection', (ws) => {
|
|
|
|
ws.on('message', (message) => {
|
|
|
|
ws.send('Echo: ' + message);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Handle upgrade requests
|
|
|
|
testServer.on('upgrade', (request, socket, head) => {
|
|
|
|
wsServer.handleUpgrade(request, socket, head, (ws) => {
|
|
|
|
wsServer.emit('connection', ws, request);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
await new Promise<void>((resolve) => testServer.listen(3000, resolve));
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('should create proxy instance', async () => {
|
2022-07-29 00:49:46 +02:00
|
|
|
testProxy = new smartproxy.NetworkProxy({
|
2022-07-29 01:52:34 +02:00
|
|
|
port: 3001,
|
2022-07-29 00:49:46 +02:00
|
|
|
});
|
2025-02-03 23:41:13 +01:00
|
|
|
expect(testProxy).toEqual(testProxy); // Instance equality check
|
2019-08-21 23:41:06 +02:00
|
|
|
});
|
|
|
|
|
2025-02-03 23:41:13 +01:00
|
|
|
tap.test('should start the proxy server', async () => {
|
2019-08-21 23:41:06 +02:00
|
|
|
await testProxy.start();
|
|
|
|
|
2025-02-03 23:41:13 +01:00
|
|
|
// Configure proxy with test certificates
|
2022-07-29 00:49:46 +02:00
|
|
|
testProxy.updateProxyConfigs([
|
2020-02-07 13:04:11 +00:00
|
|
|
{
|
2022-07-29 00:49:46 +02:00
|
|
|
destinationIp: '127.0.0.1',
|
2020-02-07 13:04:11 +00:00
|
|
|
destinationPort: '3000',
|
|
|
|
hostName: 'push.rocks',
|
2025-02-03 23:41:13 +01:00
|
|
|
publicKey: testCertificates.publicKey,
|
|
|
|
privateKey: testCertificates.privateKey,
|
2021-02-02 15:55:25 +00:00
|
|
|
},
|
2020-02-07 13:04:11 +00:00
|
|
|
]);
|
2019-09-20 18:40:55 +02:00
|
|
|
});
|
|
|
|
|
2025-02-03 23:41:13 +01:00
|
|
|
tap.test('should route HTTPS requests based on host header', async () => {
|
|
|
|
const response = await makeHttpsRequest({
|
|
|
|
hostname: 'push.rocks',
|
|
|
|
port: 3001,
|
|
|
|
path: '/',
|
|
|
|
method: 'GET',
|
|
|
|
rejectUnauthorized: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(response.statusCode).toEqual(200);
|
|
|
|
expect(response.body).toEqual('Hello from test server!');
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('should handle unknown host headers', async () => {
|
|
|
|
const response = await makeHttpsRequest({
|
|
|
|
hostname: 'unknown.host',
|
|
|
|
port: 3001,
|
|
|
|
path: '/',
|
|
|
|
method: 'GET',
|
|
|
|
rejectUnauthorized: false,
|
|
|
|
}).catch((e) => e);
|
|
|
|
|
|
|
|
expect(response instanceof Error).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('should support WebSocket connections', async () => {
|
|
|
|
return new Promise<void>((resolve, reject) => {
|
|
|
|
console.log('Starting WebSocket test...');
|
|
|
|
const ws = new WebSocket('wss://localhost:3001', {
|
|
|
|
rejectUnauthorized: false,
|
|
|
|
headers: {
|
|
|
|
'Host': 'push.rocks'
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const timeout = setTimeout(() => {
|
|
|
|
ws.close();
|
|
|
|
reject(new Error('WebSocket test timed out after 5 seconds'));
|
|
|
|
}, 5000);
|
|
|
|
|
|
|
|
ws.on('open', () => {
|
|
|
|
console.log('WebSocket connection opened');
|
|
|
|
ws.send('Hello WebSocket');
|
|
|
|
});
|
|
|
|
|
|
|
|
ws.on('message', (data) => {
|
|
|
|
console.log('Received message:', data.toString());
|
|
|
|
expect(data.toString()).toEqual('Echo: Hello WebSocket');
|
|
|
|
clearTimeout(timeout);
|
|
|
|
ws.close();
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
|
|
|
|
ws.on('error', (err) => {
|
|
|
|
console.error('WebSocket error:', err);
|
|
|
|
clearTimeout(timeout);
|
|
|
|
reject(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
ws.on('close', () => {
|
|
|
|
console.log('WebSocket connection closed');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
tap.test('should handle custom headers', async () => {
|
|
|
|
testProxy.addDefaultHeaders({
|
|
|
|
'X-Proxy-Header': 'test-value',
|
|
|
|
});
|
|
|
|
|
|
|
|
const response = await makeHttpsRequest({
|
|
|
|
hostname: 'push.rocks',
|
|
|
|
port: 3001,
|
|
|
|
path: '/',
|
|
|
|
method: 'GET',
|
|
|
|
rejectUnauthorized: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(response.headers['x-proxy-header']).toEqual('test-value');
|
2019-08-22 13:20:41 +02:00
|
|
|
});
|
|
|
|
|
2025-02-03 23:41:13 +01:00
|
|
|
tap.test('cleanup', async () => {
|
|
|
|
// Clean up all servers
|
|
|
|
await new Promise<void>((resolve) => wsServer.close(() => resolve()));
|
|
|
|
await new Promise<void>((resolve) => testServer.close(() => resolve()));
|
2019-08-21 23:41:06 +02:00
|
|
|
await testProxy.stop();
|
2019-08-20 18:42:52 +02:00
|
|
|
});
|
2019-08-20 17:50:17 +02:00
|
|
|
|
2019-08-20 18:42:52 +02:00
|
|
|
tap.start();
|