159 lines
4.4 KiB
TypeScript
159 lines
4.4 KiB
TypeScript
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
import { SmartProxy } from '../ts/index.js';
|
|
import * as http from 'http';
|
|
|
|
tap.test('should forward HTTP connections on port 8080', async (tapTest) => {
|
|
// Create a mock HTTP server to act as our target
|
|
const targetPort = 8181;
|
|
let receivedRequest = false;
|
|
let receivedPath = '';
|
|
|
|
const targetServer = http.createServer((req, res) => {
|
|
// Log request details for debugging
|
|
console.log(`Target server received: ${req.method} ${req.url}`);
|
|
receivedPath = req.url || '';
|
|
|
|
if (req.url === '/.well-known/acme-challenge/test-token') {
|
|
receivedRequest = true;
|
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
res.end('test-challenge-response');
|
|
} else {
|
|
res.writeHead(200);
|
|
res.end('OK');
|
|
}
|
|
});
|
|
|
|
await new Promise<void>((resolve) => {
|
|
targetServer.listen(targetPort, () => {
|
|
console.log(`Target server listening on port ${targetPort}`);
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
// Create SmartProxy without HttpProxy for plain HTTP
|
|
const proxy = new SmartProxy({
|
|
enableDetailedLogging: true,
|
|
routes: [{
|
|
name: 'test-route',
|
|
match: {
|
|
ports: 8080
|
|
// Remove domain restriction for HTTP connections
|
|
// Domain matching happens after HTTP headers are received
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
target: { host: 'localhost', port: targetPort }
|
|
}
|
|
}]
|
|
});
|
|
|
|
await proxy.start();
|
|
|
|
// Give the proxy a moment to fully initialize
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Make an HTTP request to port 8080
|
|
const options = {
|
|
hostname: 'localhost',
|
|
port: 8080,
|
|
path: '/.well-known/acme-challenge/test-token',
|
|
method: 'GET',
|
|
headers: {
|
|
'Host': 'test.local'
|
|
}
|
|
};
|
|
|
|
const response = await new Promise<http.IncomingMessage>((resolve, reject) => {
|
|
const req = http.request(options, (res) => resolve(res));
|
|
req.on('error', reject);
|
|
req.end();
|
|
});
|
|
|
|
// Collect response data
|
|
let responseData = '';
|
|
response.setEncoding('utf8');
|
|
response.on('data', chunk => responseData += chunk);
|
|
await new Promise(resolve => response.on('end', resolve));
|
|
|
|
// Verify the request was properly forwarded
|
|
expect(response.statusCode).toEqual(200);
|
|
expect(receivedPath).toEqual('/.well-known/acme-challenge/test-token');
|
|
expect(responseData).toEqual('test-challenge-response');
|
|
expect(receivedRequest).toEqual(true);
|
|
|
|
await proxy.stop();
|
|
await new Promise<void>((resolve) => {
|
|
targetServer.close(() => resolve());
|
|
});
|
|
});
|
|
|
|
tap.test('should handle basic HTTP request forwarding', async (tapTest) => {
|
|
// Create a simple target server
|
|
const targetPort = 8182;
|
|
let receivedRequest = false;
|
|
|
|
const targetServer = http.createServer((req, res) => {
|
|
console.log(`Target received: ${req.method} ${req.url} from ${req.headers.host}`);
|
|
receivedRequest = true;
|
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
res.end('Hello from target');
|
|
});
|
|
|
|
await new Promise<void>((resolve) => {
|
|
targetServer.listen(targetPort, () => {
|
|
console.log(`Target server listening on port ${targetPort}`);
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
// Create a simple proxy without HttpProxy
|
|
const proxy = new SmartProxy({
|
|
routes: [{
|
|
name: 'simple-forward',
|
|
match: {
|
|
ports: 8081
|
|
// Remove domain restriction for HTTP connections
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
target: { host: 'localhost', port: targetPort }
|
|
}
|
|
}]
|
|
});
|
|
|
|
await proxy.start();
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Make request
|
|
const options = {
|
|
hostname: 'localhost',
|
|
port: 8081,
|
|
path: '/test',
|
|
method: 'GET',
|
|
headers: {
|
|
'Host': 'test.local'
|
|
}
|
|
};
|
|
|
|
const response = await new Promise<http.IncomingMessage>((resolve, reject) => {
|
|
const req = http.request(options, (res) => resolve(res));
|
|
req.on('error', reject);
|
|
req.end();
|
|
});
|
|
|
|
let responseData = '';
|
|
response.setEncoding('utf8');
|
|
response.on('data', chunk => responseData += chunk);
|
|
await new Promise(resolve => response.on('end', resolve));
|
|
|
|
expect(response.statusCode).toEqual(200);
|
|
expect(responseData).toEqual('Hello from target');
|
|
expect(receivedRequest).toEqual(true);
|
|
|
|
await proxy.stop();
|
|
await new Promise<void>((resolve) => {
|
|
targetServer.close(() => resolve());
|
|
});
|
|
});
|
|
|
|
tap.start(); |