rexuws
Version:
An express-like framework built on top of uWebsocket.js aims at simple codebase and high performance
423 lines (422 loc) • 14.2 kB
TypeScript
/// <reference types="node" />
import { HttpRequest, HttpResponse, RecognizedString } from 'uWebSockets.js';
import { ReadStream } from 'fs';
export interface IIndexable {
[key: string]: unknown;
}
export interface RangeParserRanges extends Array<Range> {
type: string;
}
export interface RangeParserRange {
start: number;
end: number;
}
export interface RangeParserOptions {
/**
* The "combine" option can be set to `true` and overlapping & adjacent ranges
* will be combined into a single range.
*/
combine?: boolean;
}
export declare type RangeParserResultUnsatisfiable = -1;
export declare type RangeParserResultInvalid = -2;
export declare type RangeParserResult = RangeParserResultUnsatisfiable | RangeParserResultInvalid;
export declare enum HttpMethod {
GET = "get",
POST = "post",
PUT = "put",
PATCH = "patch",
DEL = "del",
OPTIONS = "options",
HEAD = "head",
TRACE = "trace",
CONNECT = "trace",
ANY = "any"
}
export interface CookieOptions {
maxAge?: number;
signed?: boolean;
expires?: Date;
httpOnly?: boolean;
path?: string;
domain?: string;
secure?: boolean;
encode?: (val: string) => string;
sameSite?: boolean | 'lax' | 'strict' | 'none';
}
export interface IResponseSendFileOption {
/**
* Explicitly specify mime type
*/
mime?: string;
/**
* Explicitly specify filesize (to skip fs.stat for size checking)
*/
fileSize?: number;
/**
* Defaulting to 0 (can be string converted by `ms`)
*/
maxAge?: number;
lastModified?: string;
}
export interface IRequest extends Record<string | number | symbol, unknown> {
/**
* Check if the given `type(s)` is acceptable, returning
* the best match when true, otherwise `undefined`, in which
* case you should respond with 406 "Not Acceptable".
*
* The `type` value may be a single mime type string
* such as "application/json", the extension name
* such as "json", a comma-delimted list such as "json, html, text/plain",
* or an array `["json", "html", "text/plain"]`. When a list
* or array is given the _best_ match, if any is returned.
*
* Examples:
*
* // Accept: text/html
* req.accepts('html');
* // => "html"
*
* // Accept: text/*, application/json
* req.accepts('html');
* // => "html"
* req.accepts('text/html');
* // => "text/html"
* req.accepts('json, text');
* // => "json"
* req.accepts('application/json');
* // => "application/json"
*
* // Accept: text/*, application/json
* req.accepts('image/png');
* req.accepts('png');
* // => undefined
*
* // Accept: text/*;q=.5, application/json
* req.accepts(['html', 'json']);
* req.accepts('html, json');
* // => "json"
*/
accepts(...type: string[]): string | string[] | false;
/**
* Returns the first accepted charset of the specified character sets,
* based on the request's Accept-Charset HTTP header field.
* If none of the specified charsets is accepted, returns false.
*
* For more information, or if you have issues or concerns, see accepts.
*/
acceptsCharsets(...charset: string[]): string[] | string | false;
/**
* Returns the first accepted encoding of the specified encodings,
* based on the request's Accept-Encoding HTTP header field.
* If none of the specified encodings is accepted, returns false.
*
* For more information, or if you have issues or concerns, see accepts.
*/
acceptsEncodings(...encoding: string[]): string[] | string | false;
/**
* Returns the first accepted language of the specified languages,
* based on the request's Accept-Language HTTP header field.
* If none of the specified languages is accepted, returns false.
*
* For more information, or if you have issues or concerns, see accepts.
*/
acceptsLanguages(...charset: string[]): string[] | string | false;
/**
* Request body post POST/PUT/PATCH method
*
* Without default parser, the given body is served as a Buffer
*/
body: any;
/**
* Without default parser, cookies will be served as a string
*/
cookies: any;
get(name: string): string | undefined;
/**
* Return request header.
*
* The `Referrer` header field is special-cased,
* both `Referrer` and `Referer` are interchangeable.
*
* Examples:
*
* req.get('Content-Type');
* // => "text/plain"
*
* req.get('content-type');
* // => "text/plain"
*
* req.get('Something');
* // => undefined
*
* Aliased as `req.header()`.
*/
header(name: string): string | undefined;
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains the give mime `type`.
*
* Examples:
*
* // With Content-Type: text/html; charset=utf-8
* req.is('html');
* req.is('text/html');
* req.is('text/*');
* // => true
*
* // When Content-Type is application/json
* req.is('json');
* req.is('application/json');
* req.is('application/*');
* // => true
*
* req.is('html');
* // => false
*/
is(type: string | string[]): string | false | null;
headers: Record<string, string>;
/**
* Parse the "Host" header field hostname.
*/
hostname: string | undefined;
/**
* Return the remote address
*/
ip: string;
/**
* Parse the "X-Forwarded-For" ip address list.
*
* For example if the value were "client, proxy1, proxy2"
* you would receive the array `["client", "proxy1", "proxy2"]`
* where "proxy2" is the furthest down-stream.
*/
ips: string[];
method: HttpMethod;
params: Record<string, string>;
query: Record<string, string>;
/**
* Raw body
*/
raw?: Buffer;
originalReq: HttpRequest;
url: string;
/**
* The prefixed url comming from application set up
*/
baseUrl?: string;
/**
* The expected url set up by router (omit application's modifications)
*/
originalUrl: string;
}
export interface IResponse extends Record<string | number | symbol, unknown> {
/**
* Set _Content-Type_ response header with `type` through `mime.lookup()`
* when it does not contain "/", or set the Content-Type to `type` otherwise.
*
* Examples:
*
* res.type('.html');
* res.type('html');
* res.type('json');
* res.type('application/json');
* res.type('png');
*/
contentType(type: string): this;
/**
* Set cookie `name` to `val`, with the given `options`.
*
* Options:
*
* - `maxAge` max-age in milliseconds, converted to `expires`
* - `signed` sign the cookie
* - `path` defaults to "/"
*
* Examples:
*
* // "Remember Me" for 15 minutes
* res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
*
* // save as above
* res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
*/
cookie(name: string, val: string, options: CookieOptions): this;
cookie(name: string, val: any, options: CookieOptions): this;
cookie(name: string, val: any): this;
/**
* Transfer the file at the given `path` as an attachment.
*/
download(path: string): void;
download(path: string, filename: string): void;
download(path: string, filename: string, options: any): void;
/** Get value for header `field`. */
get(field: string): string | undefined;
/** Get value for header `field`. */
getHeader(field: string): string | undefined;
/**
* Set header `field` to `val`, or pass
* an object of header fields.
*
* Examples:
*
* res.set('Foo', ['bar', 'baz']);
* res.set('Accept', 'application/json');
* res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
*
* Aliased as `res.header()`.
*/
set(field: Record<string, string | string[]>): this;
set(field: string, value?: string | string[]): this;
header(field: Record<string, string | string[]>): this;
header(field: string, value?: string | string[]): this;
/**
* Send JSON response
*/
json(body: any): void;
locals: Record<string, any>;
/**
* Set the location header to `url`.
*
* The given `url` can also be the name of a mapped url, for
* example by default express supports "back" which redirects
* to the _Referrer_ or _Referer_ headers or "/".
*
* Examples:
*
* res.location('/foo/bar').;
* res.location('http://example.com');
* res.location('../login'); // /blog/post/1 -> /blog/login
*
* Mounting:
*
* When an application is mounted and `res.location()`
* is given a path that does _not_ lead with "/" it becomes
* relative to the mount-point. For example if the application
* is mounted at "/blog", the following would become "/blog/login".
*
* res.location('login');
*
* While the leading slash would result in a location of "/login":
*
* res.location('/login');
*/
location(url: string): this;
/**
* Redirect to the given `url` with optional response `status`
* defaulting to 302.
*
* The resulting `url` is determined by `res.location()`, so
* it will play nicely with mounted apps, relative paths,
* `"back"` etc.
*
* Examples:
*
* res.redirect('/foo/bar');
* res.redirect('http://example.com');
* res.redirect(301, 'http://example.com');
* res.redirect('http://example.com', 301);
* res.redirect('../login'); // /blog/post/1 -> /blog/login
*/
redirect(url: string): void;
redirect(status: number, url: string): void;
redirect(url: string, status: number): void;
/**
* Render `view` with the given `options` and optional callback `fn`.
* When a callback function is given a response will _not_ be made
* automatically, otherwise a response of _200_ and _text/html_ is given.
*
* Options:
*
* - `cache` boolean hinting to the engine it should cache
* - `filename` filename of the view being rendered
*/
render(view: string, options?: object, callback?: (err: Error, html: string) => void): void;
render(view: string, callback?: (err: Error, html: string) => void): void;
/**
* Send a response.
*/
send(body: string | Record<string, unknown>): void;
/**
* Transfer the file at the given `path`.
*
* Automatically sets the _Content-Type_ response header field.
* The callback `fn(err)` is invoked when the transfer is complete
* or when an error occurs. Be sure to check `res.headersSent`
* if you wish to attempt responding, as the header and some data
* may have already been transferred.
*
* Options:
*
* - `maxAge` defaulting to 0 (can be string converted by `ms`)
* - `root` root directory for relative filenames
* - `headers` object of headers to serve with file
* - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them
*
* Other options are passed along to `send`.
*
* Examples:
*
* The following example illustrates how `res.sendFile()` may
* be used as an alternative for the `static()` middleware for
* dynamic situations. The code backing `res.sendFile()` is actually
* the same code, so HTTP cache support etc is identical.
*
* app.get('/user/:uid/photos/:file', function(req, res){
* var uid = req.params.uid
* , file = req.params.file;
*
* req.user.mayViewFilesFrom(uid, function(yes){
* if (yes) {
* res.sendFile('/uploads/' + uid + '/' + file);
* } else {
* res.send(403, 'Sorry! you cant see that.');
* }
* });
* });
*
* @api public
*/
sendFile(path: string, cb?: (err: any) => void): void;
sendFile(buffer: Buffer, options: IResponseSendFileOption, cb?: (err: any) => void): void;
sendFile(readStream: ReadStream, options: IResponseSendFileOption, cb?: (err: any) => void): void;
sendFile(path: string, options?: IResponseSendFileOption, cb?: (err: any) => void): void;
sendFile(path: string | Buffer | ReadStream, options?: IResponseSendFileOption | ((err: any) => void), cb?: (err: any) => void): void;
/**
* Set header `field` to `val`, or pass
* an object of header fields.
*
* Examples:
*
* res.set('Foo', ['bar', 'baz']);
* res.set('Accept', 'application/json');
* res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
*
* Aliased as `res.header()`.
*/
set(field: Record<string, string> | string, val?: string): this;
/**
* Set status `code`
*/
status(code: number): this;
/**
* Set _Content-Type_ response header with `type` through `mime.lookup()`
* when it does not contain "/", or set the Content-Type to `type` otherwise.
*
* Examples:
*
* res.type('.html');
* res.type('html');
* res.type('json');
* res.type('application/json');
* res.type('png');
*/
type(type: string): this;
end(body?: RecognizedString): void;
originalRes: HttpResponse;
}
export declare type TRequestExposedMethods = Pick<IRequest, 'get'>;
export declare type TResponseExposedMethods = Pick<HttpResponse, 'getRemoteAddressAsText' | 'getProxiedRemoteAddressAsText'>;
export declare type TApplicationExposedMethods = {
render?(...args: any): any;
};