173 lines
4.5 KiB
TypeScript
173 lines
4.5 KiB
TypeScript
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
|
import * as net from 'net';
|
|
import { SmartProxy } from '../ts/index.js';
|
|
import type { IRouteConfig } from '../ts/index.js';
|
|
|
|
let proxy: SmartProxy;
|
|
|
|
tap.test('setup socket handler test', async () => {
|
|
// Create a simple socket handler route
|
|
const routes: IRouteConfig[] = [{
|
|
name: 'echo-handler',
|
|
match: {
|
|
ports: 9999
|
|
// No domains restriction - matches all connections
|
|
},
|
|
action: {
|
|
type: 'socket-handler',
|
|
socketHandler: (socket, context) => {
|
|
console.log('Socket handler called');
|
|
// Simple echo server
|
|
socket.write('ECHO SERVER\n');
|
|
socket.on('data', (data) => {
|
|
console.log('Socket handler received data:', data.toString());
|
|
socket.write(`ECHO: ${data}`);
|
|
});
|
|
socket.on('error', (err) => {
|
|
console.error('Socket error:', err);
|
|
});
|
|
}
|
|
}
|
|
}];
|
|
|
|
proxy = new SmartProxy({
|
|
routes,
|
|
enableDetailedLogging: false
|
|
});
|
|
|
|
await proxy.start();
|
|
});
|
|
|
|
tap.test('should handle socket with custom function', async () => {
|
|
const client = new net.Socket();
|
|
let response = '';
|
|
|
|
await new Promise<void>((resolve, reject) => {
|
|
client.connect(9999, 'localhost', () => {
|
|
console.log('Client connected to proxy');
|
|
resolve();
|
|
});
|
|
|
|
client.on('error', reject);
|
|
});
|
|
|
|
// Collect data
|
|
client.on('data', (data) => {
|
|
console.log('Client received:', data.toString());
|
|
response += data.toString();
|
|
});
|
|
|
|
// Wait a bit for connection to stabilize
|
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
|
|
// Send test data
|
|
console.log('Sending test data...');
|
|
client.write('Hello World\n');
|
|
|
|
// Wait for response
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
console.log('Total response:', response);
|
|
expect(response).toContain('ECHO SERVER');
|
|
expect(response).toContain('ECHO: Hello World');
|
|
|
|
client.destroy();
|
|
});
|
|
|
|
tap.test('should handle async socket handler', async () => {
|
|
// Update route with async handler
|
|
await proxy.updateRoutes([{
|
|
name: 'async-handler',
|
|
match: { ports: 9999 },
|
|
action: {
|
|
type: 'socket-handler',
|
|
socketHandler: async (socket, context) => {
|
|
// Set up data handler first
|
|
socket.on('data', async (data) => {
|
|
console.log('Async handler received:', data.toString());
|
|
// Simulate async processing
|
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
const processed = `PROCESSED: ${data.toString().trim().toUpperCase()}\n`;
|
|
console.log('Sending:', processed);
|
|
socket.write(processed);
|
|
});
|
|
|
|
// Then simulate async operation
|
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
socket.write('ASYNC READY\n');
|
|
}
|
|
}
|
|
}]);
|
|
|
|
const client = new net.Socket();
|
|
let response = '';
|
|
|
|
// Collect data
|
|
client.on('data', (data) => {
|
|
response += data.toString();
|
|
});
|
|
|
|
await new Promise<void>((resolve, reject) => {
|
|
client.connect(9999, 'localhost', () => {
|
|
// Send initial data to trigger the handler
|
|
client.write('test data\n');
|
|
resolve();
|
|
});
|
|
|
|
client.on('error', reject);
|
|
});
|
|
|
|
// Wait for async processing
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
console.log('Final response:', response);
|
|
expect(response).toContain('ASYNC READY');
|
|
expect(response).toContain('PROCESSED: TEST DATA');
|
|
|
|
client.destroy();
|
|
});
|
|
|
|
tap.test('should handle errors in socket handler', async () => {
|
|
// Update route with error-throwing handler
|
|
await proxy.updateRoutes([{
|
|
name: 'error-handler',
|
|
match: { ports: 9999 },
|
|
action: {
|
|
type: 'socket-handler',
|
|
socketHandler: (socket, context) => {
|
|
throw new Error('Handler error');
|
|
}
|
|
}
|
|
}]);
|
|
|
|
const client = new net.Socket();
|
|
let connectionClosed = false;
|
|
|
|
client.on('close', () => {
|
|
connectionClosed = true;
|
|
});
|
|
|
|
await new Promise<void>((resolve, reject) => {
|
|
client.connect(9999, 'localhost', () => {
|
|
// Connection established - send data to trigger handler
|
|
client.write('trigger\n');
|
|
resolve();
|
|
});
|
|
|
|
client.on('error', () => {
|
|
// Ignore client errors - we expect the connection to be closed
|
|
});
|
|
});
|
|
|
|
// Wait a bit
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
// Socket should be closed due to handler error
|
|
expect(connectionClosed).toEqual(true);
|
|
});
|
|
|
|
tap.test('cleanup', async () => {
|
|
await proxy.stop();
|
|
});
|
|
|
|
export default tap.start(); |