UNPKG

@webda/core

Version:

Expose API with Lambda

313 lines 8 kB
import { parse as cookieParse } from "cookie"; import { Readable } from "stream"; /** * All methods supported by Webda */ export const HttpMethodTypeAny = ["GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"]; /** * The HttpContext * * It has similar properties than URL * * @see https://developer.mozilla.org/en-US/docs/Web/API/URL_API * * @category CoreFeatures */ export class HttpContext { constructor(hostname, method, uri, protocol = "http", port = "80", headers = {}) { /** * URI prefix in case it is exposed through something that prefix the uri */ this.prefix = ""; this.hostname = hostname; this.method = method; this.uri = uri; [this.path, this.search] = uri.split("?"); if (this.search) { this.search = "?" + this.search; } else { this.search = ""; } // @ts-ignore this.protocol = protocol + ":"; this.port = port.toString(); this.headers = {}; for (let i in headers) { if (i.toLowerCase() === "cookie") { this.cookies = Array.isArray(headers[i]) ? headers[i].map(c => cookieParse(c)) : cookieParse(headers[i]); } this.headers[i.toLowerCase()] = headers[i]; } let portUrl = ""; if (port !== undefined && ((this.port !== "80" && protocol === "http") || (this.port !== "443" && protocol === "https"))) { portUrl = ":" + port; } else { this.port = ""; } this.origin = this.protocol + "//" + this.hostname + portUrl; this.host = this.hostname + portUrl; } /** * Set the client ip */ setClientIp(ip) { this.clientIp = ip; return this; } /** * Get the client ip */ getClientIp() { return this.clientIp; } /** * * @see https://developer.mozilla.org/en-US/docs/Web/API/URL/href * @returns */ getHref() { return this.getAbsoluteUrl(); } /** * * @param prefix uri to not consider */ setPrefix(prefix) { if (prefix.endsWith("/")) { prefix = prefix.substring(0, prefix.length - 1); } this.prefix = prefix; } /** * Return Uri without prefix */ getRelativeUri() { return this.uri.substring(this.prefix.length); } /** * Get full URI * @returns */ getUrl() { return this.uri; } /** * Get cookies * @returns */ getCookies() { return this.cookies; } /** * Get port number as string * * If http on port 80, or https on port 443 will return "" */ getPort() { return this.port; } /** * Get the port number */ getPortNumber() { if (this.port) { return Number.parseInt(this.port); } if (this.protocol === "https:") { return 443; } else { return 80; } } /** * Return hostname and port * @returns */ getHost() { return this.host; } /** * Return protocol, hostname and port * @returns */ getOrigin() { return this.origin; } /** * Get the hostname * @returns */ getHostName() { return this.hostname; } /** * Get HTTP Method used * @returns */ getMethod() { return this.method; } /** * Get protocol used * @returns */ getProtocol() { return this.protocol; } /** * Get the raw body as string * * @param limit the size of readable request * @param timeout the time to read the request * @param encoding to analyze * @returns */ async getRawBodyAsString(limit = 1024 * 1024 * 10, timeout = 60000, encoding) { // Get charset from header if (!encoding) { let match = this.getUniqueHeader("content-type", "charset=utf-8").match(/charset=([^;\s]+)/); if (match) { encoding = match[1].trim(); } else { encoding = "utf-8"; } } if (encoding !== "utf-8") { throw new Error("Only UTF-8 is currently managed: https://github.com/loopingz/webda.io/issues/221"); } return ((await this.getRawBody(limit, timeout)) || Buffer.from("")).toString(encoding); } /** * Get request body * * @param limit the size of readable request * @param timeout the time to read the request * @returns */ async getRawBody(limit = 1024 * 1024 * 10, timeout = 60000) { if (this.body instanceof Readable) { return new Promise((resolve, reject) => { let req = this.body; let body = []; let timeoutId = setTimeout(() => { reject("Request timeout"); }, timeout); req.on("readable", () => { let chunk = req.read(); if (chunk !== null) { if (chunk.length + body.length > limit) { clearTimeout(timeoutId); reject("Request oversized"); } body.push(chunk); } }); req.on("end", () => { clearTimeout(timeoutId); // Cache body as stream won't be able to be read twice this.body = Buffer.concat(body); resolve(this.body); }); }); } else { return this.body; } } /** * Get the body as stream */ getRawStream() { if (this.body instanceof Readable) { return this.body; } return Readable.from(this.body || Buffer.from("")); } /** * Get HTTP Headers * @returns */ getHeaders() { return this.headers; } /** * Get header value * @param name * @param def * @returns */ getHeader(name, def) { return this.headers[name.toLowerCase()] || def; } /** * Return the last header found with that name */ getUniqueHeader(name, def) { let header = this.getHeader(name, def); if (Array.isArray(header)) { return header.pop() || def; } return header || def; } /** * Used for test * @param body */ setBody(body) { if (body instanceof Readable || body instanceof Buffer) { this.body = body; } else if (typeof body === "string") { this.body = Buffer.from(body); } else if (body === undefined) { this.body = undefined; } else { this.body = Buffer.from(JSON.stringify(body)); } return this; } /** * Get request path name * * @see https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname * @returns */ getPathName() { return this.path; } /** * Get search section * * @see https://developer.mozilla.org/en-US/docs/Web/API/URL/search * @returns */ getSearch() { return this.search; } /** * * @param uri to return absolute url from */ getAbsoluteUrl(uri = this.uri) { if (uri.match(/^\w{1,10}:\/\//)) { return uri; } if (!uri.startsWith("/")) { uri = "/" + uri; } if (this.port) { return `${this.protocol}//${this.hostname}:${this.port}${uri}`; } return `${this.protocol}//${this.hostname}${uri}`; } } //# sourceMappingURL=httpcontext.js.map