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.

151 lines 11.8 kB
import * as types from './types.js'; import { CoreResponse } from './response.js'; import { CoreRequest as AbstractCoreRequest } from '../core_base/request.js'; /** * Fetch-based implementation of Core Request class */ export class CoreRequest extends AbstractCoreRequest { constructor(url, options = {}) { super(url, options); this.timeoutId = null; this.abortController = null; // Check for unsupported Node.js-specific options if (options.agent || options.socketPath) { throw new Error('Node.js specific options (agent, socketPath) are not supported in browser/fetch implementation'); } } /** * Build the full URL with query parameters */ buildUrl() { if (!this.options.queryParams || Object.keys(this.options.queryParams).length === 0) { return this.url; } const url = new URL(this.url); Object.entries(this.options.queryParams).forEach(([key, value]) => { url.searchParams.append(key, value); }); return url.toString(); } /** * Convert our options to fetch RequestInit */ buildFetchOptions() { const fetchOptions = { method: this.options.method, headers: this.options.headers, credentials: this.options.credentials, mode: this.options.mode, cache: this.options.cache, redirect: this.options.redirect, referrer: this.options.referrer, referrerPolicy: this.options.referrerPolicy, integrity: this.options.integrity, keepalive: this.options.keepAlive, signal: this.options.signal, }; // Handle request body if (this.options.requestBody !== undefined) { if (typeof this.options.requestBody === 'string' || this.options.requestBody instanceof ArrayBuffer || this.options.requestBody instanceof Uint8Array || this.options.requestBody instanceof FormData || this.options.requestBody instanceof URLSearchParams || this.options.requestBody instanceof ReadableStream || // Check for Buffer (Node.js polyfills in browser may provide this) (typeof Buffer !== 'undefined' && this.options.requestBody instanceof Buffer)) { fetchOptions.body = this.options.requestBody; // If streaming, we need to set duplex mode if (this.options.requestBody instanceof ReadableStream) { fetchOptions.duplex = 'half'; } } else { // Convert objects to JSON fetchOptions.body = JSON.stringify(this.options.requestBody); // Set content-type if not already set if (!fetchOptions.headers) { fetchOptions.headers = { 'Content-Type': 'application/json' }; } else if (fetchOptions.headers instanceof Headers) { if (!fetchOptions.headers.has('Content-Type')) { fetchOptions.headers.set('Content-Type', 'application/json'); } } else if (typeof fetchOptions.headers === 'object' && !Array.isArray(fetchOptions.headers)) { const headersObj = fetchOptions.headers; if (!headersObj['Content-Type']) { headersObj['Content-Type'] = 'application/json'; } } } } // Handle timeout if (this.options.timeout || this.options.hardDataCuttingTimeout) { const timeout = this.options.hardDataCuttingTimeout || this.options.timeout; this.abortController = new AbortController(); this.timeoutId = setTimeout(() => { if (this.abortController) { this.abortController.abort(); } }, timeout); fetchOptions.signal = this.abortController.signal; } return fetchOptions; } /** * Fire the request and return a CoreResponse */ async fire() { const response = await this.fireCore(); return new CoreResponse(response); } /** * Fire the request and return the raw Response */ async fireCore() { const url = this.buildUrl(); const options = this.buildFetchOptions(); try { const response = await fetch(url, options); // Clear timeout on successful response this.clearTimeout(); return response; } catch (error) { // Clear timeout on error this.clearTimeout(); if (error.name === 'AbortError') { throw new Error('Request timed out'); } throw error; } } /** * Clear the timeout and abort controller */ clearTimeout() { if (this.timeoutId) { clearTimeout(this.timeoutId); this.timeoutId = null; } if (this.abortController) { this.abortController = null; } } /** * Static factory method to create and fire a request */ static async create(url, options = {}) { const request = new CoreRequest(url, options); return request.fire(); } } /** * Convenience exports for backward compatibility */ export const isUnixSocket = CoreRequest.isUnixSocket; export const parseUnixSocketUrl = CoreRequest.parseUnixSocketUrl; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmVfZmV0Y2gvcmVxdWVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssS0FBSyxNQUFNLFlBQVksQ0FBQztBQUNwQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxXQUFXLElBQUksbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUU3RTs7R0FFRztBQUNILE1BQU0sT0FBTyxXQUFZLFNBQVEsbUJBR2hDO0lBSUMsWUFBWSxHQUFXLEVBQUUsVUFBcUMsRUFBRTtRQUM5RCxLQUFLLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBSmQsY0FBUyxHQUF5QyxJQUFJLENBQUM7UUFDdkQsb0JBQWUsR0FBMkIsSUFBSSxDQUFDO1FBS3JELGlEQUFpRDtRQUNqRCxJQUFJLE9BQU8sQ0FBQyxLQUFLLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxLQUFLLENBQ2IsZ0dBQWdHLENBQ2pHLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssUUFBUTtRQUNkLElBQ0UsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQ2xELENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDbEIsQ0FBQztRQUVELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QixNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFD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