@planet-a/affinity-node
Version:
API wrapper for the affinity.co API
257 lines (256 loc) • 7.26 kB
JavaScript
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
});
}
}