UNPKG

@adonisjs/http-server

Version:

AdonisJS HTTP server with support packed with Routing and Cookies

564 lines (563 loc) 17.3 kB
import Macroable from '@poppinss/macroable'; import { UrlWithStringQuery } from 'node:url'; import type { Encryption } from '@adonisjs/encryption'; import { ServerResponse, IncomingMessage, IncomingHttpHeaders } from 'node:http'; import type { Qs } from './qs.js'; import { RequestConfig } from './types/request.js'; import type { HttpContext } from './http_context/main.js'; /** * HTTP Request class exposes the interface to consistently read values * related to a given HTTP request. The class is wrapper over * [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) * and has extended API. * * You can access the original [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) * using `request.request` property. */ export declare class Request extends Macroable { #private; request: IncomingMessage; response: ServerResponse; /** * Parses copy of the URL with query string as a string and not * object. This is done to build URL's with query string without * stringifying the object */ parsedUrl: UrlWithStringQuery; /** * The ctx will be set by the context itself. It creates a circular * reference */ ctx?: HttpContext; constructor(request: IncomingMessage, response: ServerResponse, encryption: Encryption, config: RequestConfig, qsParser: Qs); /** * Returns the request id from the `x-request-id` header. The * header is untouched, if it already exists. */ id(): string | undefined; /** * Set initial request body. A copy of the input will be maintained as the original * request body. Since the request body and query string is subject to mutations, we * keep one original reference to flash old data (whenever required). * * This method is supposed to be invoked by the body parser and must be called only * once. For further mutations make use of `updateBody` method. */ setInitialBody(body: Record<string, any>): void; /** * Update the request body with new data object. The `all` property * will be re-computed by merging the query string and request * body. */ updateBody(body: Record<string, any>): void; /** * Update the request raw body. Bodyparser sets this when unable to parse * the request body or when request is multipart/form-data. */ updateRawBody(rawBody: string): void; /** * Update the query string with the new data object. The `all` property * will be re-computed by merging the query and the request body. */ updateQs(data: Record<string, any>): void; /** * Returns route params */ params(): Record<string, any>; /** * Returns the query string object by reference */ qs(): Record<string, any>; /** * Returns reference to the request body */ body(): Record<string, any>; /** * Returns reference to the merged copy of request body * and query string */ all(): Record<string, any>; /** * Returns reference to the merged copy of original request * query string and body */ original(): Record<string, any>; /** * Returns the request raw body (if exists), or returns `null`. * * Ideally you must be dealing with the parsed body accessed using [[input]], [[all]] or * [[post]] methods. The `raw` body is always a string. */ raw(): string | null; /** * Returns value for a given key from the request body or query string. * The `defaultValue` is used when original value is `undefined`. * * @example * ```js * request.input('username') * * // with default value * request.input('username', 'virk') * ``` */ input(key: string, defaultValue?: any): any; /** * Returns value for a given key from route params * * @example * ```js * request.param('id') * * // with default value * request.param('id', 1) * ``` */ param(key: string, defaultValue?: any): any; /** * Get everything from the request body except the given keys. * * @example * ```js * request.except(['_csrf']) * ``` */ except(keys: string[]): Record<string, any>; /** * Get value for specified keys. * * @example * ```js * request.only(['username', 'age']) * ``` */ only<T extends string>(keys: T[]): { [K in T]: any; }; /** * Returns the HTTP request method. This is the original * request method. For spoofed request method, make * use of [[method]]. * * @example * ```js * request.intended() * ``` */ intended(): string; /** * Returns the request HTTP method by taking method spoofing into account. * * Method spoofing works when all of the following are true. * * 1. `app.http.allowMethodSpoofing` config value is true. * 2. request query string has `_method`. * 3. The [[intended]] request method is `POST`. * * @example * ```js * request.method() * ``` */ method(): string; /** * Returns a copy of headers as an object */ headers(): IncomingHttpHeaders; /** * Returns value for a given header key. The default value is * used when original value is `undefined`. */ header(key: string, defaultValue?: any): string | undefined; /** * Returns the ip address of the user. This method is optimize to fetch * ip address even when running your AdonisJs app behind a proxy. * * You can also define your own custom function to compute the ip address by * defining `app.http.getIp` as a function inside the config file. * * ```js * { * http: { * getIp (request) { * // I am using nginx as a proxy server and want to trust 'x-real-ip' * return request.header('x-real-ip') * } * } * } * ``` * * You can control the behavior of trusting the proxy values by defining it * inside the `config/app.js` file. * * ```js * { * http: { * trustProxy: '127.0.0.1' * } * } * ``` * * The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr) */ ip(): string; /** * Returns an array of ip addresses from most to least trusted one. * This method is optimize to fetch ip address even when running * your AdonisJs app behind a proxy. * * You can control the behavior of trusting the proxy values by defining it * inside the `config/app.js` file. * * ```js * { * http: { * trustProxy: '127.0.0.1' * } * } * ``` * * The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr) */ ips(): string[]; /** * Returns the request protocol by checking for the URL protocol or * `X-Forwarded-Proto` header. * * If the `trust` is evaluated to `false`, then URL protocol is returned, * otherwise `X-Forwarded-Proto` header is used (if exists). * * You can control the behavior of trusting the proxy values by defining it * inside the `config/app.js` file. * * ```js * { * http: { * trustProxy: '127.0.0.1' * } * } * ``` * * The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr) */ protocol(): string; /** * Returns a boolean telling if request is served over `https` * or not. Check [[protocol]] method to know how protocol is * fetched. */ secure(): boolean; /** * Returns the request host. If proxy headers are trusted, then * `X-Forwarded-Host` is given priority over the `Host` header. * * You can control the behavior of trusting the proxy values by defining it * inside the `config/app.js` file. * * ```js * { * http: { * trustProxy: '127.0.0.1' * } * } * ``` * * The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr) */ host(): string | null; /** * Returns the request hostname. If proxy headers are trusted, then * `X-Forwarded-Host` is given priority over the `Host` header. * * You can control the behavior of trusting the proxy values by defining it * inside the `config/app.js` file. * * ```js * { * http: { * trustProxy: '127.0.0.1' * } * } * ``` * * The value of trustProxy is passed directly to [proxy-addr](https://www.npmjs.com/package/proxy-addr) */ hostname(): string | null; /** * Returns an array of subdomains for the given host. An empty array is * returned if [[hostname]] is `null` or is an IP address. * * Also `www` is not considered as a subdomain */ subdomains(): string[]; /** * Returns a boolean telling, if request `X-Requested-With === 'xmlhttprequest'` * or not. */ ajax(): boolean; /** * Returns a boolean telling, if request has `X-Pjax` header * set or not */ pjax(): boolean; /** * Returns the request relative URL. * * @example * ```js * request.url() * * // include query string * request.url(true) * ``` */ url(includeQueryString?: boolean): string; /** * Returns the complete HTTP url by combining * [[protocol]]://[[hostname]]/[[url]] * * @example * ```js * request.completeUrl() * * // include query string * request.completeUrl(true) * ``` */ completeUrl(includeQueryString?: boolean): string; /** * Find if the current HTTP request is for the given route or the routes */ matchesRoute(routeIdentifier: string | string[]): boolean; /** * Returns the best matching content type of the request by * matching against the given types. * * The content type is picked from the `content-type` header and request * must have body. * * The method response highly depends upon the types array values. Described below: * * | Type(s) | Return value | * |----------|---------------| * | ['json'] | json | * | ['application/*'] | application/json | * | ['vnd+json'] | application/json | * * @example * ```js * const bodyType = request.is(['json', 'xml']) * * if (bodyType === 'json') { * // process JSON * } * * if (bodyType === 'xml') { * // process XML * } * ``` */ is(types: string[]): string | null; /** * Returns the best type using `Accept` header and * by matching it against the given types. * * If nothing is matched, then `null` will be returned * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. * * @example * ```js * switch (request.accepts(['json', 'html'])) { * case 'json': * return response.json(user) * case 'html': * return view.render('user', { user }) * default: * // decide yourself * } * ``` */ accepts<T extends string>(types: T[]): T | null; /** * Return the types that the request accepts, in the order of the * client's preference (most preferred first). * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. */ types(): string[]; /** * Returns the best language using `Accept-language` header * and by matching it against the given languages. * * If nothing is matched, then `null` will be returned * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. * * @example * ```js * switch (request.language(['fr', 'de'])) { * case 'fr': * return view.render('about', { lang: 'fr' }) * case 'de': * return view.render('about', { lang: 'de' }) * default: * return view.render('about', { lang: 'en' }) * } * ``` */ language<T extends string>(languages: T[]): T | null; /** * Return the languages that the request accepts, in the order of the * client's preference (most preferred first). * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. */ languages(): string[]; /** * Returns the best charset using `Accept-charset` header * and by matching it against the given charsets. * * If nothing is matched, then `null` will be returned * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. * * @example * ```js * switch (request.charset(['utf-8', 'ISO-8859-1'])) { * case 'utf-8': * // make utf-8 friendly response * case 'ISO-8859-1': * // make ISO-8859-1 friendly response * } * ``` */ charset<T extends string>(charsets: T[]): T | null; /** * Return the charsets that the request accepts, in the order of the * client's preference (most preferred first). * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. */ charsets(): string[]; /** * Returns the best encoding using `Accept-encoding` header * and by matching it against the given encodings. * * If nothing is matched, then `null` will be returned * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. */ encoding<T extends string>(encodings: T[]): T | null; /** * Return the charsets that the request accepts, in the order of the * client's preference (most preferred first). * * Make sure to check [accepts](https://www.npmjs.com/package/accepts) package * docs too. */ encodings(): string[]; /** * Returns a boolean telling if request has body */ hasBody(): boolean; /** * Returns a boolean telling if the new response etag evaluates same * as the request header `if-none-match`. In case of `true`, the * server must return `304` response, telling the browser to * use the client cache. * * You won't have to deal with this method directly, since AdonisJs will * handle this for you when `http.etag = true` inside `config/app.js` file. * * However, this is how you can use it manually. * * ```js * const responseBody = view.render('some-view') * * // sets the HTTP etag header for response * response.setEtag(responseBody) * * if (request.fresh()) { * response.sendStatus(304) * } else { * response.send(responseBody) * } * ``` */ fresh(): boolean; /** * Opposite of [[fresh]] */ stale(): boolean; /** * Returns all parsed and signed cookies. Signed cookies ensures * that their value isn't tampered. */ cookiesList(): Record<string, any>; /** * Returns value for a given key from signed cookies. Optional * defaultValue is returned when actual value is undefined. */ cookie(key: string, defaultValue?: string): any; /** * Returns value for a given key from signed cookies. Optional * defaultValue is returned when actual value is undefined. */ encryptedCookie(key: string, defaultValue?: string): any; /** * Returns value for a given key from unsigned cookies. Optional * defaultValue is returned when actual value is undefined. */ plainCookie(key: string, options?: { defaultValue?: string; encoded?: boolean; }): any; plainCookie(key: string, defaultValue?: string, encoded?: boolean): any; /** * Returns a boolean telling if a signed url as a valid signature * or not. */ hasValidSignature(purpose?: string): boolean; /** * Serializes request to JSON format */ serialize(): { id: string | undefined; url: string; query: string | null; body: Record<string, any>; params: Record<string, any>; headers: IncomingHttpHeaders; method: string; protocol: string; cookies: Record<string, any>; hostname: string | null; ip: string; subdomains: Record<string, any>; }; /** * toJSON copy of the request */ toJSON(): { id: string | undefined; url: string; query: string | null; body: Record<string, any>; params: Record<string, any>; headers: IncomingHttpHeaders; method: string; protocol: string; cookies: Record<string, any>; hostname: string | null; ip: string; subdomains: Record<string, any>; }; }