UNPKG

@push.rocks/smartrequest

Version:

A module for modern HTTP/HTTPS requests with support for form data, file uploads, JSON, binary data, streams, and more.

111 lines 8.24 kB
import * as plugins from './plugins.js'; import * as types from './types.js'; import { CoreResponse as AbstractCoreResponse } from '../core_base/response.js'; /** * Node.js implementation of Core Response class that provides a fetch-like API */ export class CoreResponse extends AbstractCoreResponse { constructor(incomingMessage, url, options = {}) { super(); this.bodyBufferPromise = null; this._autoDrainTimeout = null; this.incomingMessage = incomingMessage; this.url = url; this.status = incomingMessage.statusCode || 0; this.statusText = incomingMessage.statusMessage || ''; this.ok = this.status >= 200 && this.status < 300; this.headers = incomingMessage.headers; // Auto-drain unconsumed streams to prevent socket hanging // This prevents keep-alive sockets from timing out when response bodies aren't consumed // Default to true if not specified if (options.autoDrain !== false) { this._autoDrainTimeout = setImmediate(() => { if (!this.consumed && !this.incomingMessage.readableEnded) { console.log(`Auto-draining unconsumed response body for ${this.url} (status: ${this.status})`); this.incomingMessage.resume(); // Drain without processing } }); } } /** * Override to also cancel auto-drain when body is consumed */ ensureNotConsumed() { // Cancel auto-drain since we're consuming the body if (this._autoDrainTimeout) { clearImmediate(this._autoDrainTimeout); this._autoDrainTimeout = null; } super.ensureNotConsumed(); } /** * Collects the body as a buffer */ async collectBody() { this.ensureNotConsumed(); if (this.bodyBufferPromise) { return this.bodyBufferPromise; } this.bodyBufferPromise = new Promise((resolve, reject) => { const chunks = []; this.incomingMessage.on('data', (chunk) => { chunks.push(chunk); }); this.incomingMessage.on('end', () => { resolve(Buffer.concat(chunks)); }); this.incomingMessage.on('error', reject); }); return this.bodyBufferPromise; } /** * Parse response as JSON */ async json() { const buffer = await this.collectBody(); const text = buffer.toString('utf-8'); try { return JSON.parse(text); } catch (error) { throw new Error(`Failed to parse JSON: ${error.message}`); } } /** * Get response as text */ async text() { const buffer = await this.collectBody(); return buffer.toString('utf-8'); } /** * Get response as ArrayBuffer */ async arrayBuffer() { const buffer = await this.collectBody(); const sliced = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); // Ensure we return ArrayBuffer, not SharedArrayBuffer return sliced instanceof ArrayBuffer ? sliced : new ArrayBuffer(0); } /** * Get response as a web-style ReadableStream */ stream() { this.ensureNotConsumed(); // Convert Node.js stream to web stream using Readable.toWeb() // This creates a proper Node.js-compatible web stream that works with Readable.fromWeb() if (this.incomingMessage.readableEnded || this.incomingMessage.destroyed) { return null; } // Use Readable.toWeb() to convert Node.js stream to web stream (Node.js 16.5+) // The returned type is automatically Node.js ReadableStream which is compatible with Readable.fromWeb() return plugins.stream.Readable.toWeb(this.incomingMessage); } /** * Get the raw IncomingMessage (for legacy compatibility) */ raw() { return this.incomingMessage; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzcG9uc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jb3JlX25vZGUvcmVzcG9uc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLEtBQUssTUFBTSxZQUFZLENBQUM7QUFDcEMsT0FBTyxFQUFFLFlBQVksSUFBSSxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRWhGOztHQUVHO0FBQ0gsTUFBTSxPQUFPLFlBQ1gsU0FBUSxvQkFBdUI7SUFjL0IsWUFDRSxlQUE2QyxFQUM3QyxHQUFXLEVBQ1gsVUFBcUMsRUFBRTtRQUV2QyxLQUFLLEVBQUUsQ0FBQztRQWZGLHNCQUFpQixHQUEyQixJQUFJLENBQUM7UUFDakQsc0JBQWlCLEdBQTRCLElBQUksQ0FBQztRQWV4RCxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxNQUFNLEdBQUcsZUFBZSxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUM7UUFDOUMsSUFBSSxDQUFDLFVBQVUsR0FBRyxlQUFlLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztRQUN0RCxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO1FBQ2xELElBQUksQ0FBQyxPQUFPLEdBQUcsZUFBZSxDQUFDLE9BQU8sQ0FBQztRQUV2QywwREFBMEQ7UUFDMUQsd0ZBQXdGO1FBQ3hGLG1DQUFtQztRQUNuQyxJQUFJLE9BQU8sQ0FBQyxTQUFTLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLFlBQVksQ0FBQyxHQUFHLEVBQUU7Z0JBQ3pDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztvQkFDMUQsT0FBTyxDQUFDLEdBQUcsQ0FDVCw4Q0FBOEMsSUFBSSxDQUFDLEdBQUcsYUFBYSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQ2xGLENBQUM7b0JBQ0YsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLDJCQUEyQjtnQkFDNUQsQ0FBQztZQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNPLGlCQUFpQjtRQUN6QixtREFBbUQ7UUFDbkQsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUMzQixjQUFjLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztRQUNoQyxDQUFDO1FBRUQsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLFdBQVc7UUFDdkIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFFekIsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUMzQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztRQUNoQyxDQUFDO1FBRUQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQy9ELE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztZQUU1QixJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRTtnQkFDaEQsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNyQixDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUU7Z0JBQ2xDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDakMsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDM0MsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsSUFBSTtRQUNSLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFdEMsSUFBSSxDQUFDO1lBQ0gsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDNUQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxJQUFJO1FBQ1IsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDeEMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxXQUFXO1FBQ2YsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDeEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2hDLE1BQU0sQ0FBQyxVQUFVLEVBQ2pCLE1BQU0sQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FDdEMsQ0FBQztRQUNGLHNEQUFzRDtRQUN0RCxPQUFPLE1BQU0sWUFBWSxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTTtRQUNKLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRXpCLDhEQUE4RDtRQUM5RCx5RkFBeUY7UUFDekYsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3pFLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELCtFQUErRTtRQUMvRSx3R0FBd0c7UUFDeEcsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBUSxDQUFDO0lBQ3BFLENBQUM7SUFFRDs7T0FFRztJQUNILEdBQUc7UUFDRCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDOUIsQ0FBQztDQUNGIn0=