@push.rocks/smartproxy
Version:
A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.
78 lines • 7.5 kB
JavaScript
import * as plugins from '../../../plugins.js';
import { createLogger } from '../models/types.js';
import { HttpStatus, getStatusText } from '../models/http-types.js';
/**
* Handles HTTP redirect routes
*/
export class RedirectHandler {
/**
* Handle redirect routes
*/
static async handleRedirect(socket, route, context) {
const { connectionId, connectionManager, settings } = context;
const logger = context.logger || createLogger(settings.logLevel || 'info');
const action = route.action;
// We should have a redirect configuration
if (!action.redirect) {
logger.error(`[${connectionId}] Redirect action missing redirect configuration`);
socket.end();
connectionManager.cleanupConnection({ id: connectionId }, 'missing_redirect');
return;
}
// For TLS connections, we can't do redirects at the TCP level
// This check should be done before calling this handler
// Wait for the first HTTP request to perform the redirect
const dataListeners = [];
const httpDataHandler = (chunk) => {
// Remove all data listeners to avoid duplicated processing
for (const listener of dataListeners) {
socket.removeListener('data', listener);
}
// Parse HTTP request to get path
try {
const headersEnd = chunk.indexOf('\r\n\r\n');
if (headersEnd === -1) {
// Not a complete HTTP request, need more data
socket.once('data', httpDataHandler);
dataListeners.push(httpDataHandler);
return;
}
const httpHeaders = chunk.slice(0, headersEnd).toString();
const requestLine = httpHeaders.split('\r\n')[0];
const [method, path] = requestLine.split(' ');
// Extract Host header
const hostMatch = httpHeaders.match(/Host: (.+?)(\r\n|\r|\n|$)/i);
const host = hostMatch ? hostMatch[1].trim() : '';
// Process the redirect URL with template variables
let redirectUrl = action.redirect.to;
redirectUrl = redirectUrl.replace(/\{domain\}/g, host);
redirectUrl = redirectUrl.replace(/\{path\}/g, path || '');
redirectUrl = redirectUrl.replace(/\{port\}/g, socket.localPort?.toString() || '80');
// Prepare the HTTP redirect response
const redirectResponse = [
`HTTP/1.1 ${action.redirect.status} Moved`,
`Location: ${redirectUrl}`,
'Connection: close',
'Content-Length: 0',
'',
'',
].join('\r\n');
if (settings.enableDetailedLogging) {
logger.info(`[${connectionId}] Redirecting to ${redirectUrl} with status ${action.redirect.status}`);
}
// Send the redirect response
socket.end(redirectResponse);
connectionManager.initiateCleanupOnce({ id: connectionId }, 'redirect_complete');
}
catch (err) {
logger.error(`[${connectionId}] Error processing HTTP redirect: ${err}`);
socket.end();
connectionManager.initiateCleanupOnce({ id: connectionId }, 'redirect_error');
}
};
// Setup the HTTP data handler
socket.once('data', httpDataHandler);
dataListeners.push(httpDataHandler);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkaXJlY3QtaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3Byb3hpZXMvaHR0cC1wcm94eS9oYW5kbGVycy9yZWRpcmVjdC1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFJL0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFTcEU7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUMxQjs7T0FFRztJQUNJLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUNoQyxNQUEwQixFQUMxQixLQUFtQixFQUNuQixPQUFnQztRQUVoQyxNQUFNLEVBQUUsWUFBWSxFQUFFLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUM5RCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLFlBQVksQ0FBQyxRQUFRLENBQUMsUUFBUSxJQUFJLE1BQU0sQ0FBQyxDQUFDO1FBQzNFLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFFNUIsMENBQTBDO1FBQzFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDckIsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLFlBQVksa0RBQWtELENBQUMsQ0FBQztZQUNqRixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDYixpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1lBQzlFLE9BQU87UUFDVCxDQUFDO1FBRUQsOERBQThEO1FBQzlELHdEQUF3RDtRQUV4RCwwREFBMEQ7UUFDMUQsTUFBTSxhQUFhLEdBQWdDLEVBQUUsQ0FBQztRQUV0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