/** * HTTP Protocol Detector * * Simplified HTTP detection using the new architecture */ import type { IProtocolDetector } from '../models/interfaces.js'; import type { IDetectionResult, IDetectionOptions } from '../models/detection-types.js'; import type { IProtocolDetectionResult, IConnectionContext } from '../../protocols/common/types.js'; import type { THttpMethod } from '../../protocols/http/index.js'; import { QuickProtocolDetector } from './quick-detector.js'; import { RoutingExtractor } from './routing-extractor.js'; import { DetectionFragmentManager } from '../utils/fragment-manager.js'; /** * Simplified HTTP detector */ export class HttpDetector implements IProtocolDetector { private quickDetector = new QuickProtocolDetector(); private fragmentManager: DetectionFragmentManager; constructor(fragmentManager?: DetectionFragmentManager) { this.fragmentManager = fragmentManager || new DetectionFragmentManager(); } /** * Check if buffer can be handled by this detector */ canHandle(buffer: Buffer): boolean { const result = this.quickDetector.quickDetect(buffer); return result.protocol === 'http' && result.confidence > 50; } /** * Get minimum bytes needed for detection */ getMinimumBytes(): number { return 4; // "GET " minimum } /** * Detect HTTP protocol from buffer */ detect(buffer: Buffer, options?: IDetectionOptions): IDetectionResult | null { // Quick detection first const quickResult = this.quickDetector.quickDetect(buffer); if (quickResult.protocol !== 'http' || quickResult.confidence < 50) { return null; } // Check if we have complete headers first const headersEnd = buffer.indexOf('\r\n\r\n'); const isComplete = headersEnd !== -1; // Extract routing information const routing = RoutingExtractor.extract(buffer, 'http'); // If we don't need full headers and we have complete headers, we can return early if (quickResult.confidence >= 95 && !options?.extractFullHeaders && isComplete) { return { protocol: 'http', connectionInfo: { protocol: 'http', method: quickResult.metadata?.method as THttpMethod, domain: routing?.domain, path: routing?.path }, isComplete: true }; } return { protocol: 'http', connectionInfo: { protocol: 'http', domain: routing?.domain, path: routing?.path, method: quickResult.metadata?.method as THttpMethod }, isComplete, bytesNeeded: isComplete ? undefined : buffer.length + 512 // Need more for headers }; } /** * Handle fragmented detection */ detectWithContext( buffer: Buffer, context: IConnectionContext, options?: IDetectionOptions ): IDetectionResult | null { const handler = this.fragmentManager.getHandler('http'); const connectionId = DetectionFragmentManager.createConnectionId(context); // Add fragment const result = handler.addFragment(connectionId, buffer); if (result.error) { handler.complete(connectionId); return null; } // Try detection on accumulated buffer const detectResult = this.detect(result.buffer!, options); if (detectResult && detectResult.isComplete) { handler.complete(connectionId); } return detectResult; } }