UNPKG

@curveball/kernel

Version:

Curveball is a framework writting in Typescript for Node.js

151 lines 4.52 kB
import Accepts from 'accepts'; import * as url from 'node:url'; import { is, parsePrefer } from './header-helpers.js'; import { Headers } from './headers.js'; /** * This interface represents an incoming server request. */ export class Request { constructor(method, requestTarget, origin) { this.method = method; this.requestTarget = requestTarget; this.headers = new Headers(); this.origin = origin; } /** * List of HTTP Headers */ headers; /** * path-part of the request. * * For example /hello/world */ get path() { return url.parse(this.requestTarget).pathname; } /** * Sets the request path */ set path(value) { this.requestTarget = value; } /** * HTTP method * * For example: GET */ method; /** * The request target. * * This contains the literal value after the HTTP method in the request. * So for: * * GET /foo HTTP/1.1 * * This would contain '/foo'. In many cases this is the same as the 'path' * property, but there's 3 other forms in the HTTP specificatio. Here's the * different formats: * * * origin-form - This is the most common. Example: /foo. * * absolute-form - Clients might sent an entire path. Also used by proxies. * Example: https://example.org/foo * * authority-form - Used by the CONNECT method. Example: example.org:1212 * * asterisk-form - Used by the OPTIONS method. Example: * * * In most cases users will want to use the 'path' property instead. only use * this if you know what you're doing. * * @see {@link https://tools.ietf.org/html/rfc7230#section-5.3} */ requestTarget; /** * Contains a parsed, stored representation of the body. It's up to * middlewares to do the actual parsing. */ body; /** * This object contains parsed query parameters. */ get query() { return url.parse(this.requestTarget, true).query; } /** * Returns the value of the Content-Type header, with any additional * parameters such as charset= removed. * * If there was no Content-Type header, an empty string will be returned. */ get type() { const type = this.headers.get('content-type'); if (!type) { return ''; } return type.split(';')[0]; } /** * accepts is used for negotation the Content-Type with a client. * * You can pass a content-type, or an array of content-types. * The Content-Types you provide are a list of types your application * supports. * * This function will then return the best possible type based on the Accept * header. * * If no compatible types are found, this function returns null. */ accepts(...types) { const mockRequestObj = { headers: { accept: this.headers.get('Accept') } }; // @ts-expect-error The types for the Accept package are probably not 100% correct for ESM. const result = new Accepts(mockRequestObj).type(types); return result === false ? null : result; } /** * This method will return true or false if a Request or Response has a * Content-Type header that matches the argument. * * For example, if the Content-Type header has the value: application/hal+json, * then the arguments will all return true: * * * application/hal+json * * application/json * * hal+json * * json * * application/* */ is(type) { return is(this, type); } prefer(preference) { const prefer = parsePrefer(this.headers.get('Prefer')); const val = prefer[preference]; if (val === undefined) { return false; } return val; } /** * Returns the absolute url for this request. * * This may not always be correct, because it's based on a best guess. * If you have a reverse proxy in front of your curveball server, you may * need to provide a 'origin' argument when constructing the server. */ get absoluteUrl() { return this.origin + this.requestTarget; } /** * Public base URL * * This will be used to determine the absoluteUrl */ origin; } export default Request; //# sourceMappingURL=request.js.map