Fetch-based HTTP request handler for browser applications as part of the Smithy TypeScript ecosystem
npx @tessl/cli install tessl/npm-smithy--fetch-http-handler@4.1.0@smithy/fetch-http-handler is a TypeScript library that provides a fetch-based HTTP request handler specifically designed for browser applications as part of the Smithy TypeScript ecosystem. It implements the default requestHandler used in browser environments, leveraging the modern Fetch API to handle HTTP requests with support for request timeouts, streaming responses, and proper error handling.
npm install @smithy/fetch-http-handlerimport { FetchHttpHandler, streamCollector } from "@smithy/fetch-http-handler";
import type { FetchHttpHandlerOptions } from "@smithy/fetch-http-handler";For CommonJS:
const { FetchHttpHandler, streamCollector } = require("@smithy/fetch-http-handler");import { FetchHttpHandler } from "@smithy/fetch-http-handler";
import { HttpRequest } from "@smithy/protocol-http";
// Create handler with options
const handler = new FetchHttpHandler({
requestTimeout: 5000,
keepAlive: true,
credentials: 'same-origin'
});
// Handle an HTTP request
const request = new HttpRequest({
method: "GET",
hostname: "api.example.com",
path: "/users",
headers: { "Accept": "application/json" }
});
const { response } = await handler.handle(request);
console.log(response.statusCode, response.headers);
// Use static create method
const handler2 = FetchHttpHandler.create({
requestTimeout: 10000
});The package is built around several key components:
Core HTTP request handling using the Fetch API with comprehensive configuration options and error handling.
class FetchHttpHandler implements HttpHandler<FetchHttpHandlerOptions> {
constructor(options?: FetchHttpHandlerOptions | Provider<FetchHttpHandlerOptions | void>);
static create(
instanceOrOptions?: HttpHandler<any> | FetchHttpHandlerOptions | Provider<FetchHttpHandlerOptions | void>
): HttpHandler<any> | FetchHttpHandler;
handle(request: HttpRequest, options?: HttpHandlerOptions): Promise<{ response: HttpResponse }>;
destroy(): void;
updateHttpClientConfig(key: keyof FetchHttpHandlerOptions, value: FetchHttpHandlerOptions[typeof key]): void;
httpHandlerConfigs(): FetchHttpHandlerOptions;
}Usage Examples:
import { FetchHttpHandler } from "@smithy/fetch-http-handler";
import { HttpRequest } from "@smithy/protocol-http";
// Basic handler with timeout
const handler = new FetchHttpHandler({
requestTimeout: 5000
});
// Handle POST request with body
const postRequest = new HttpRequest({
method: "POST",
hostname: "api.example.com",
path: "/data",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key: "value" })
});
const { response } = await handler.handle(postRequest);
// Handle request with abort signal
const controller = new AbortController();
const { response: abortableResponse } = await handler.handle(
postRequest,
{ abortSignal: controller.signal }
);
// Update configuration dynamically
handler.updateHttpClientConfig("requestTimeout", 10000);Utilities for collecting data from Blob or ReadableStream objects into Uint8Array format.
/**
* Collects data from a Blob or ReadableStream into a Uint8Array
* @param stream - Blob or ReadableStream to collect data from
* @returns Promise resolving to collected data as Uint8Array
*/
const streamCollector: StreamCollector = (stream: Blob | ReadableStream): Promise<Uint8Array>;
type StreamCollector = (stream: Blob | ReadableStream) => Promise<Uint8Array>;Usage Examples:
import { streamCollector } from "@smithy/fetch-http-handler";
// Collect from ReadableStream
const response = await fetch('/api/data');
if (response.body) {
const data = await streamCollector(response.body);
console.log('Collected bytes:', data.length);
}
// Collect from Blob
const blob = new Blob(['Hello, world!']);
const uint8Array = await streamCollector(blob);
console.log('Blob as bytes:', uint8Array);Comprehensive configuration interface for customizing HTTP request behavior.
interface FetchHttpHandlerOptions {
/**
* The number of milliseconds a request can take before being automatically
* terminated.
*/
requestTimeout?: number;
/**
* Whether to allow the request to outlive the page. Default value is false.
*
* There may be limitations to the payload size, number of concurrent requests,
* request duration etc. when using keepalive in browsers.
*
* These may change over time, so look for up to date information about
* these limitations before enabling keepalive.
*/
keepAlive?: boolean;
/**
* A string indicating whether credentials will be sent with the request always, never, or
* only when sent to a same-origin URL.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
*/
credentials?: "include" | "omit" | "same-origin" | undefined | string;
/**
* Cache settings for fetch.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request/cache
*/
cache?: "default" | "force-cache" | "no-cache" | "no-store" | "only-if-cached" | "reload";
/**
* An optional function that produces additional RequestInit
* parameters for each httpRequest.
*
* This is applied last via merging with Object.assign() and overwrites other values
* set from other sources.
*
* @example
* ```js
* new Client({
* requestHandler: {
* requestInit(httpRequest) {
* return { cache: "no-store" };
* }
* }
* });
* ```
*/
requestInit?: (httpRequest: HttpRequest) => RequestInit;
}
interface HttpHandlerOptions {
/** AbortSignal to cancel the request */
abortSignal?: AbortSignal;
}
type Provider<T> = () => Promise<T>;Internal utilities used by the FetchHttpHandler for request creation and timeout management.
/**
* Creates a Request object for mocking/interception support
* @param url - Target URL for the request
* @param requestOptions - Optional RequestInit options
* @returns New Request object
*/
function createRequest(
url: string,
requestOptions?: RequestInit & AdditionalRequestParameters
): Request;
/**
* Creates a timeout promise that rejects after specified milliseconds
* @param timeoutInMs - Timeout duration in milliseconds (0 disables timeout)
* @returns Promise that rejects with TimeoutError
*/
function requestTimeout(timeoutInMs?: number): Promise<never>;
type AdditionalRequestParameters = {
/** Required in Node.js when Request has a body */
duplex?: "half";
};
const keepAliveSupport: {
supported: undefined | boolean;
};interface HttpRequest {
method: string;
protocol: string;
hostname: string;
port?: number;
path: string;
query?: Record<string, string>;
fragment?: string;
headers: HeaderBag;
username?: string;
password?: string;
body?: any;
}
interface HttpResponse {
statusCode: number;
reason?: string;
headers: HeaderBag;
body: any;
}
type HeaderBag = Record<string, string>;
interface HttpHandler<T> {
handle(request: HttpRequest, options?: HttpHandlerOptions): Promise<{ response: HttpResponse }>;
}The library handles several types of errors:
try {
const { response } = await handler.handle(request);
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request was aborted');
} else if (error.name === 'TimeoutError') {
console.log('Request timed out');
} else {
console.log('Other error:', error.message);
}
}