UNPKG

@rdfc/http-utils-processor-ts

Version:
114 lines (113 loc) 3.8 kB
import { HttpUtilsError } from "./error.js"; import { timeout } from "./util/timeout.js"; import { statusCodeAccepted } from "./util/status.js"; import { parseHeaders } from "./util/headers.js"; import { Auth } from "./auth/index.js"; import { cronify } from "./util/cronify.js"; import { getLoggerFor } from "./util/logUtil.js"; const logger = getLoggerFor("httpFetch"); class HttpFetchArgs { method = "GET"; headers = []; acceptStatusCodes = ["200-300"]; closeOnEnd = true; bodyCanBeEmpty = false; timeOutMilliseconds = null; auth = null; cron = null; runOnInit = false; errorsAreFatal = true; outputAsBuffer = false; constructor(partial) { Object.assign(this, partial); if (!partial.bodyCanBeEmpty && partial.method == "HEAD") { throw HttpUtilsError.illegalParameters("Cannot use HEAD method with bodyCanBeEmpty set to false"); } if (partial.closeOnEnd && partial.cron) { throw HttpUtilsError.illegalParameters("Cannot close stream when using cron."); } if (this.acceptStatusCodes.length === 0) { this.acceptStatusCodes.push("200-300"); } statusCodeAccepted(0, this.acceptStatusCodes); } getAuth() { return this.auth ? Auth.from(this.auth) : null; } } export async function httpFetch(url, writer, options = {}) { url = (Array.isArray(url) ? url : [url]); const args = new HttpFetchArgs(options); const auth = args.getAuth(); const headers = parseHeaders(args.headers); const requests = url.map((x) => { return new Request(x, { method: options.method, headers, }); }); const executeRequest = async (req) => { logger.debug(`Executing request to '${req.url}'...`); if (auth) { await auth.authorize(req); } const fetchPromise = fetch(req).catch((err) => { throw HttpUtilsError.genericFetchError(err); }); const res = await timeout(args.timeOutMilliseconds, fetchPromise).catch((err) => { if (err === "timeout") { throw HttpUtilsError.timeOutError(args.timeOutMilliseconds); } else { throw err; } }); if (!statusCodeAccepted(res.status, args.acceptStatusCodes)) { if (res.status === 401 && auth) { throw HttpUtilsError.credentialIssue(); } else if (res.status === 401) { throw HttpUtilsError.unauthorizedError(); } else { throw HttpUtilsError.statusCodeNotAccepted(res.status); } } if (!res.body) { if (!args.bodyCanBeEmpty) { throw HttpUtilsError.noBodyInResponse(); } if (!args.cron && args.closeOnEnd) { await writer.end(); } return; } try { const body = args.outputAsBuffer ? Buffer.from(await res.arrayBuffer()) : await res.text(); await writer.push(body); } catch (e) { console.error(e); } }; let executeAllRequests = async () => { const promises = requests.map(executeRequest).map((promise) => promise.catch((err) => { if (args.errorsAreFatal) { throw err; } else { console.error(err); } })); await Promise.all(promises); if (args.closeOnEnd) { await writer.end(); } }; if (args.cron) { executeAllRequests = cronify(executeAllRequests, args.cron, args.runOnInit); } return executeAllRequests; }