UNPKG

@planet-a/affinity-node

Version:
257 lines (256 loc) 7.26 kB
import * as dntShim from "../../../_dnt.shims.js"; import { from } from '../rxjsStub.js'; /** * Represents an HTTP method. */ export var HttpMethod; (function (HttpMethod) { HttpMethod["GET"] = "GET"; HttpMethod["HEAD"] = "HEAD"; HttpMethod["POST"] = "POST"; HttpMethod["PUT"] = "PUT"; HttpMethod["DELETE"] = "DELETE"; HttpMethod["CONNECT"] = "CONNECT"; HttpMethod["OPTIONS"] = "OPTIONS"; HttpMethod["TRACE"] = "TRACE"; HttpMethod["PATCH"] = "PATCH"; })(HttpMethod || (HttpMethod = {})); export class HttpException extends Error { constructor(msg) { super(msg); } } function ensureAbsoluteUrl(url) { if (url.startsWith("http://") || url.startsWith("https://")) { return url; } return globalThis.location.origin + url; } /** * Represents an HTTP request context */ export class RequestContext { /** * Creates the request context using a http method and request resource url * * @param url url of the requested resource * @param httpMethod http method */ constructor(url, httpMethod) { Object.defineProperty(this, "httpMethod", { enumerable: true, configurable: true, writable: true, value: httpMethod }); Object.defineProperty(this, "headers", { enumerable: true, configurable: true, writable: true, value: {} }); Object.defineProperty(this, "body", { enumerable: true, configurable: true, writable: true, value: undefined }); Object.defineProperty(this, "url", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "signal", { enumerable: true, configurable: true, writable: true, value: undefined }); this.url = new URL(ensureAbsoluteUrl(url)); } /* * Returns the url set in the constructor including the query string * */ getUrl() { return this.url.toString().endsWith("/") ? this.url.toString().slice(0, -1) : this.url.toString(); } /** * Replaces the url set in the constructor with this url. * */ setUrl(url) { this.url = new URL(ensureAbsoluteUrl(url)); } /** * Sets the body of the http request either as a string or FormData * * Note that setting a body on a HTTP GET, HEAD, DELETE, CONNECT or TRACE * request is discouraged. * https://httpwg.org/http-core/draft-ietf-httpbis-semantics-latest.html#rfc.section.7.3.1 * * @param body the body of the request */ setBody(body) { this.body = body; } getHttpMethod() { return this.httpMethod; } getHeaders() { return this.headers; } getBody() { return this.body; } setQueryParam(name, value) { this.url.searchParams.set(name, value); } appendQueryParam(name, value) { this.url.searchParams.append(name, value); } /** * Sets a cookie with the name and value. NO check for duplicate cookies is performed * */ addCookie(name, value) { if (!this.headers["Cookie"]) { this.headers["Cookie"] = ""; } this.headers["Cookie"] += name + "=" + value + "; "; } setHeaderParam(key, value) { this.headers[key] = value; } setSignal(signal) { this.signal = signal; } getSignal() { return this.signal; } } /** * Helper class to generate a `ResponseBody` from binary data */ export class SelfDecodingBody { constructor(dataSource) { Object.defineProperty(this, "dataSource", { enumerable: true, configurable: true, writable: true, value: dataSource }); } binary() { return this.dataSource; } async text() { const data = await this.dataSource; return data.text(); } } export class ResponseContext { constructor(httpStatusCode, headers, body) { Object.defineProperty(this, "httpStatusCode", { enumerable: true, configurable: true, writable: true, value: httpStatusCode }); Object.defineProperty(this, "headers", { enumerable: true, configurable: true, writable: true, value: headers }); Object.defineProperty(this, "body", { enumerable: true, configurable: true, writable: true, value: body }); } /** * Parse header value in the form `value; param1="value1"` * * E.g. for Content-Type or Content-Disposition * Parameter names are converted to lower case * The first parameter is returned with the key `""` */ getParsedHeader(headerName) { const result = {}; if (!this.headers[headerName]) { return result; } const parameters = this.headers[headerName].split(";"); for (const parameter of parameters) { let [key, value] = parameter.split("=", 2); if (!key) { continue; } key = key.toLowerCase().trim(); if (value === undefined) { result[""] = key; } else { value = value.trim(); if (value.startsWith('"') && value.endsWith('"')) { value = value.substring(1, value.length - 1); } result[key] = value; } } return result; } async getBodyAsFile() { const data = await this.body.binary(); const fileName = this.getParsedHeader("content-disposition")["filename"] || ""; const contentType = this.headers["content-type"] || ""; try { return new dntShim.File([data], fileName, { type: contentType }); } catch (error) { /** Fallback for when the File constructor is not available */ return Object.assign(data, { name: fileName, type: contentType }); } } /** * Use a heuristic to get a body of unknown data structure. * Return as string if possible, otherwise as binary. */ getBodyAsAny() { try { return this.body.text(); } catch { } try { return this.body.binary(); } catch { } return Promise.resolve(undefined); } } export function wrapHttpLibrary(promiseHttpLibrary) { return { send(request) { return from(promiseHttpLibrary.send(request)); } }; } export class HttpInfo extends ResponseContext { constructor(httpStatusCode, headers, body, data) { super(httpStatusCode, headers, body); Object.defineProperty(this, "data", { enumerable: true, configurable: true, writable: true, value: data }); } }