UNPKG

cdk-amazon-chime-resources

Version:

![Experimental](https://img.shields.io/badge/experimental-important.svg?style=for-the-badge)

99 lines (98 loc) 4.11 kB
import { HttpResponse } from "@aws-sdk/protocol-http"; import { buildQueryString } from "@aws-sdk/querystring-builder"; import { Agent as hAgent, request as hRequest } from "http"; import { Agent as hsAgent, request as hsRequest } from "https"; import { NODEJS_TIMEOUT_ERROR_CODES } from "./constants"; import { getTransformedHeaders } from "./get-transformed-headers"; import { writeRequestBody } from "./write-request-body"; export const DEFAULT_REQUEST_TIMEOUT = 0; export class NodeHttpHandler { constructor(options) { this.metadata = { handlerProtocol: "http/1.1" }; this.configProvider = new Promise((resolve, reject) => { if (typeof options === "function") { options() .then((_options) => { resolve(this.resolveDefaultConfig(_options)); }) .catch(reject); } else { resolve(this.resolveDefaultConfig(options)); } }); } resolveDefaultConfig(options) { const { requestTimeout, connectionTimeout, socketTimeout, httpAgent, httpsAgent } = options || {}; const keepAlive = true; const maxSockets = 50; return { connectionTimeout, socketTimeout, requestTimeout: requestTimeout ?? connectionTimeout ?? socketTimeout ?? DEFAULT_REQUEST_TIMEOUT, httpAgent: httpAgent || new hAgent({ keepAlive, maxSockets }), httpsAgent: httpsAgent || new hsAgent({ keepAlive, maxSockets }), }; } destroy() { this.config?.httpAgent?.destroy(); this.config?.httpsAgent?.destroy(); } async handle(request, { abortSignal } = {}) { if (!this.config) { this.config = await this.configProvider; } return new Promise((resolve, reject) => { if (!this.config) { throw new Error("Node HTTP request handler config is not resolved"); } if (abortSignal?.aborted) { const abortError = new Error("Request aborted"); abortError.name = "AbortError"; reject(abortError); return; } const isSSL = request.protocol === "https:"; const queryString = buildQueryString(request.query || {}); const nodeHttpsOptions = { headers: request.headers, host: request.hostname, method: request.method, path: queryString ? `${request.path}?${queryString}` : request.path, port: request.port, agent: isSSL ? this.config.httpsAgent : this.config.httpAgent, }; const requestFunc = isSSL ? hsRequest : hRequest; const req = requestFunc(nodeHttpsOptions, (res) => { const httpResponse = new HttpResponse({ statusCode: res.statusCode || -1, headers: getTransformedHeaders(res.headers), body: res, }); resolve({ response: httpResponse }); }); req.on("error", (err) => { if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) { reject(Object.assign(err, { name: "TimeoutError" })); } else { reject(err); } }); const timeout = this.config?.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT; req.setTimeout(timeout, () => { req.destroy(); reject(Object.assign(new Error(`Connection timed out after ${timeout} ms`), { name: "TimeoutError" })); }); if (abortSignal) { abortSignal.onabort = () => { req.abort(); const abortError = new Error("Request aborted"); abortError.name = "AbortError"; reject(abortError); }; } writeRequestBody(req, request); }); } }