This repository has been archived on 2024-09-11. You can view files and clone it, but cannot push or open issues or pull requests.
svrjs-blog-newsletter/cronjob/node_modules/@smithy/fetch-http-handler/dist-es/fetch-http-handler.js
2024-05-26 22:54:55 +02:00

118 lines
4.4 KiB
JavaScript

import { HttpResponse } from "@smithy/protocol-http";
import { buildQueryString } from "@smithy/querystring-builder";
import { requestTimeout } from "./request-timeout";
export const keepAliveSupport = {
supported: Boolean(typeof Request !== "undefined" && "keepalive" in new Request("https://[::1]")),
};
export class FetchHttpHandler {
static create(instanceOrOptions) {
if (typeof instanceOrOptions?.handle === "function") {
return instanceOrOptions;
}
return new FetchHttpHandler(instanceOrOptions);
}
constructor(options) {
if (typeof options === "function") {
this.configProvider = options().then((opts) => opts || {});
}
else {
this.config = options ?? {};
this.configProvider = Promise.resolve(this.config);
}
}
destroy() {
}
async handle(request, { abortSignal } = {}) {
if (!this.config) {
this.config = await this.configProvider;
}
const requestTimeoutInMs = this.config.requestTimeout;
const keepAlive = this.config.keepAlive === true;
if (abortSignal?.aborted) {
const abortError = new Error("Request aborted");
abortError.name = "AbortError";
return Promise.reject(abortError);
}
let path = request.path;
const queryString = buildQueryString(request.query || {});
if (queryString) {
path += `?${queryString}`;
}
if (request.fragment) {
path += `#${request.fragment}`;
}
let auth = "";
if (request.username != null || request.password != null) {
const username = request.username ?? "";
const password = request.password ?? "";
auth = `${username}:${password}@`;
}
const { port, method } = request;
const url = `${request.protocol}//${auth}${request.hostname}${port ? `:${port}` : ""}${path}`;
const body = method === "GET" || method === "HEAD" ? undefined : request.body;
const requestOptions = {
body,
headers: new Headers(request.headers),
method: method,
};
if (body) {
requestOptions.duplex = "half";
}
if (typeof AbortController !== "undefined") {
requestOptions.signal = abortSignal;
}
if (keepAliveSupport.supported) {
requestOptions.keepalive = keepAlive;
}
const fetchRequest = new Request(url, requestOptions);
const raceOfPromises = [
fetch(fetchRequest).then((response) => {
const fetchHeaders = response.headers;
const transformedHeaders = {};
for (const pair of fetchHeaders.entries()) {
transformedHeaders[pair[0]] = pair[1];
}
const hasReadableStream = response.body != undefined;
if (!hasReadableStream) {
return response.blob().then((body) => ({
response: new HttpResponse({
headers: transformedHeaders,
reason: response.statusText,
statusCode: response.status,
body,
}),
}));
}
return {
response: new HttpResponse({
headers: transformedHeaders,
reason: response.statusText,
statusCode: response.status,
body: response.body,
}),
};
}),
requestTimeout(requestTimeoutInMs),
];
if (abortSignal) {
raceOfPromises.push(new Promise((resolve, reject) => {
abortSignal.onabort = () => {
const abortError = new Error("Request aborted");
abortError.name = "AbortError";
reject(abortError);
};
}));
}
return Promise.race(raceOfPromises);
}
updateHttpClientConfig(key, value) {
this.config = undefined;
this.configProvider = this.configProvider.then((config) => {
config[key] = value;
return config;
});
}
httpHandlerConfigs() {
return this.config ?? {};
}
}