UNPKG

@tunframework/tun

Version:

tun framework for node with typescript

484 lines (462 loc) 16.5 kB
/// <reference types="node" /> import { EventEmitter } from 'events'; import { IncomingHttpHeaders } from 'http'; import { IncomingMessage } from 'http'; import { ListenOptions } from 'net'; import { OutgoingHttpHeaders } from 'http'; import { Server } from 'http'; import { ServerResponse } from 'http'; import { Socket } from 'net'; import { Stream } from 'stream'; import { URL as URL_2 } from 'url'; import { URLSearchParams as URLSearchParams_2 } from 'url'; export declare function compose<Context>(composables: TunComposable<Context>[]): (ctx: Context, next?: TunComposable<Context> | undefined) => Promise<any>; /** * Wrapped file for formidable */ declare interface File_2 { size: number; path: string; name: string; type: string; lastModifiedDate?: Date; hash?: string; toJSON(): Object; } export { File_2 as File } /* Excluded from this release type: _getRequestCookieByName */ export declare class HttpError extends Error { status: number; constructor({ status, message, error }: HttpErrorOptions); } export declare interface HttpErrorOptions { status?: number; message?: string; error?: Error; } /** * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods */ export declare const HttpMethod: { readonly GET: "GET"; readonly HEAD: "HEAD"; readonly POST: "POST"; readonly PUT: "PUT"; readonly DELETE: "DELETE"; readonly CONNECT: "CONNECT"; readonly OPTIONS: "OPTIONS"; readonly TRACE: "TRACE"; readonly PATCH: "PATCH"; }; /** * @see https://stackoverflow.com/questions/50784444/add-description-attribute-to-enum-and-read-this-description-in-typescript */ export declare const HttpStatus: { readonly CONTINUE: 100; readonly SWITCHING_PROTOCOLS: 101; readonly PROCESSING: 102; readonly OK: 200; readonly CREATED: 201; readonly ACCEPTED: 202; readonly NON_AUTHORITATIVE_INFORMATION: 203; readonly NO_CONTENT: 204; readonly RESET_CONTENT: 205; readonly PARTIAL_CONTENT: 206; readonly MULTI_STATUS: 207; readonly ALREADY_REPORTED: 208; readonly IM_USED: 226; readonly MULTIPLE_CHOICES: 300; readonly MOVED_PERMANENTLY: 301; readonly FOUND: 302; readonly SEE_OTHER: 303; readonly NOT_MODIFIED: 304; readonly USE_PROXY: 305; readonly TEMPORARY_REDIRECT: 307; readonly PERMANENT_REDIRECT: 308; readonly BAD_REQUEST: 400; readonly UNAUTHORIZED: 401; readonly PAYMENT_REQUIRED: 402; readonly FORBIDDEN: 403; readonly NOT_FOUND: 404; readonly METHOD_NOT_ALLOWED: 405; readonly NOT_ACCEPTABLE: 406; readonly PROXY_AUTHENTICATION_REQUIRED: 407; readonly REQUEST_TIMEOUT: 408; readonly CONFLICT: 409; readonly GONE: 410; readonly LENGTH_REQUIRED: 411; readonly PRECONDITION_FAILED: 412; readonly PAYLOAD_TOO_LARGE: 413; readonly URI_TOO_LONG: 414; readonly UNSUPPORTED_MEDIA_TYPE: 415; readonly RANGE_NOT_SATISFIABLE: 416; readonly EXPECTATION_FAILED: 417; readonly IM_A_TEAPOT: 418; readonly UNPROCESSABLE_ENTITY: 422; readonly LOCKED: 423; readonly FAILED_DEPENDENCY: 424; readonly UPGRADE_REQUIRED: 426; readonly PRECONDITION_REQUIRED: 428; readonly TOO_MANY_REQUESTS: 429; readonly REQUEST_HEADER_FIELDS_TOO_LARGE: 431; readonly INTERNAL_SERVER_ERROR: 500; readonly NOT_IMPLEMENTED: 501; readonly BAD_GATEWAY: 502; readonly SERVICE_UNAVAILABLE: 503; readonly GATEWAY_TIMEOUT: 504; readonly HTTP_VERSION_NOT_SUPPORTED: 505; readonly VARIANT_ALSO_NEGOTIATES: 506; readonly INSUFFICIENT_STORAGE: 507; readonly LOOP_DETECTED: 508; readonly NOT_EXTENDED: 510; readonly NETWORK_AUTHENTICATION_REQUIRED: 511; }; /** * Map for ranslate `HttpStatus` */ export declare const HttpStatusMessage: Record<number, string>; export declare const mimeExtMap: Record<string, string>; export declare const RAW_REQUEST: unique symbol; export declare const RAW_RESPONSE: unique symbol; /* Excluded from this release type: _stringifyTunCookie */ export declare class TunApplication extends EventEmitter { middleware: TunComposable<TunContext>[]; mountObj: Record<string, any>; constructor(); use(fn: TunComposable<TunContext> | TunComposable<TunContext>): this; mount(name: string, obj: any): void; callback(): (_req: IncomingMessage, _res: ServerResponse) => Promise<void>; listen(option?: ListenOptions): Server; } export declare type TunComposable<Context> = (ctx: Context, next: () => Promise<any>) => Promise<any> | void; export declare class TunContext { req: TunRequest; res: TunResponse; /** * sth you may need to store and access */ state: Record<string, any>; constructor(_req: IncomingMessage, _res: ServerResponse); /** * shorthand for `res.body` */ get body(): string | Object | any[] | Stream | Buffer | null; set body(val: string | Object | any[] | Stream | Buffer | null); getRequestCookie(name: string): string | undefined; } export declare interface TunCookie { name: string; value: string; domain?: string; path?: string; maxAge?: number; expires?: Date; httpOnly?: boolean; secure?: boolean; } export declare class TunRequest { #private; [RAW_REQUEST]: IncomingMessage; /** * formdata fields * @see [bodyparser](https://github.com/tunframework/tun-bodyparser) */ fields: Record<string, string>; _fields: Record<string, string | Array<string>>; /** * formdata files * @see [bodyparser](https://github.com/tunframework/tun-bodyparser) */ files: Record<string, File_2>; _files: Record<string, File_2 | File_2[]>; /** * request body * @see [bodyparser](https://github.com/tunframework/tun-bodyparser) */ body: any; /** * @example "/product/abc" matches "/product/:id", ctx.req.slugs.id === "abc" * @see [rest-router](https://github.com/tunframework/tun-rest-router) */ slugs: Record<string, any>; constructor(req: IncomingMessage, options?: TunRequestOptions); get header(): IncomingHttpHeaders; set header(val: IncomingHttpHeaders); get headers(): IncomingHttpHeaders; set headers(val: IncomingHttpHeaders); /** * * http methods * * refers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods * * Get/Set request method, useful for implementing middleware such as methodOverride(). * */ get method(): "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE" | "PATCH"; set method(val: "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "CONNECT" | "OPTIONS" | "TRACE" | "PATCH"); /** * Return request Content-Length as a number when preqent, or undefined. */ get length(): number | undefined; get url(): string; set url(val: string); get originalUrl(): string | undefined; /** * Get origin of URL, include protocol and host. * @example http://example.com */ get origin(): string | undefined; /** * Get full request URL, include protocol, host and url. * @example http://example.com/foo/bar?q=1 */ get href(): string; get path(): string; set path(val: string); get querystring(): string; set querystring(val: string); get search(): string; set search(val: string); /** * Get host (hostname:port) when present. * Supports X-Forwarded-Host when app.proxy is true, * otherwise Host is used. */ get host(): string | undefined; /** * Get hostname when present. * Supports X-Forwarded-Host when app.proxy is true, * otherwise Host is used. * * //// ignore: If host is IPv6, delegates parsing to WHATWG URL API, Note This may impact performance. */ get hostname(): string; /** * Get WHATWG parsed URL object. * * refers: https://nodebeginner.org/blog/post/nodejs-tutorial-whatwg-url-parser/ * * url模块现在(node 8.0+)提供了一个额外的实现,它实现了标准化的WHATWG URL API,使得Node.js的url-parsing代码与Web浏览器解析URL的方式相同 * * 原有的 'url.parse()' Nodejs 被认为 */ get URL(): URL_2; get type(): string; /** * Get request charset when present, or undefined: * @example "utf-8" */ get charset(): string | undefined; get query(): URLSearchParams_2; set query(val: URLSearchParams_2); get protocol(): string | string[]; get secure(): boolean; /** * Request remote address. Supports X-Forwarded-For when app.proxy is true. */ get ip(): string | undefined; /** * When X-Forwarded-For is present and app.proxy is enabled an array of these ips is returned, * ordered from upstream to downstream. * When disabled an empty array is returned. * * refers: https://support.stackpath.com/hc/en-us/articles/360021658292-Getting-Real-Client-IPs-with-X-Forwarded-For */ get ips(): (string | undefined)[]; /** * Return subdomains as an array. * * Subdomains are the dot-separated parts of the host before the main domain of the app. * By default, the domain of the app is assumed to be the last two parts of the host. * This can be changed by setting app.subdomainOffset. * * For example, if the domain is "tobi.ferrets.example.com": If app.subdomainOffset is not set, * ctx.subdomains is ["ferrets", "tobi"]. * If app.subdomainOffset is 3, ctx.subdomains is ["tobi"]. */ get subdomains(): string[]; /** * Check if the incoming request contains the "Content-Type" header field, * and it contains any of the give mime types. * If there is no request body, null is returned. * If there is no content type, or the match fails false is returned. * Otherwise, it returns the matching content-type. */ is(...types: string[]): string | false; /** * Check if the given type(s) is acceptable, * returning the best match when true, otherwise false. * The type value may be one or more mime type string such as "application/json", * the extension name such as "json", * or an array ["json", "html", "text/plain"]. * * refers: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept */ accepts(...types: string[]): string | false; /** * Check if encodings are acceptable, * returning the best match when true, otherwise false. * Note that you should include identity as one of the encodings! * * // Accept-Encoding: gzip * ctx.acceptsEncodings('gzip', 'deflate', 'identity'); * // "gzip" * * ctx.acceptsEncodings(['gzip', 'deflate', 'identity']); * // "gzip" * * Note that the identity encoding (which means no encoding) * could be unacceptable if the client explicitly sends identity;q=0. * Although this is an edge case, * you should still handle the case where this method returns false. */ acceptsEncodings(...encodings: Array<string | string[]>): string | boolean | string[]; /** * Check if charsets are acceptable, * returning the best match when true, otherwise false. */ acceptsCharsets(...charsets: string[]): string | boolean; /** * Check if langs are acceptable, * returning the best match when true, * otherwise false. * * When no arguments are given all accepted languages are returned as an array * * refers: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Language * @returns return wheather (given) languages acceptable, or all accepted languages (when no arguments are given) */ acceptsLanguages(...langs: Array<string | string[]>): string | boolean | string[]; /** * Check if the request is idempotent. * * refers: https://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html */ idempotent(): boolean; get socket(): Socket; /** * Return request header. * * field lower-kebad-case-field-name */ get(field: string): string | string[] | undefined; } export declare interface TunRequestOptions { proxy?: boolean; subdomainOffset?: number; } export declare class TunResponse { #private; [RAW_REQUEST]: IncomingMessage; [RAW_RESPONSE]: ServerResponse; cookies: TunCookie[]; constructor(req: IncomingMessage, res: ServerResponse); get header(): OutgoingHttpHeaders; get headers(): OutgoingHttpHeaders; get socket(): Socket | null; get status(): number; set status(val: number); /** * Get response status message. * By default, it is associated with response.status. */ get message(): string; set message(val: string); set length(val: number); /** * Return response Content-Length as a number when present, * or deduce from ctx.body when possible, or undefined. */ get length(): number; get body(): string | Buffer | Stream | Object | Array<any> | null; set body(val: string | Buffer | Stream | Object | Array<any> | null); /** * Get a response header field value with case-insensitive field. * * e.g. const etag = ctx.response.get('ETag'); */ get(field: string): string | number | string[] | undefined; /** * Set response header field to value: * * e.g. `ctx.request.set('Cache-Control', 'no-cache');` * ``` * ctx.request.set({ * 'Etag': '1234', * 'Last-Modified': date * }) * ``` */ set(field: string, value: string | number | string[]): void; /** * Append additional header field with value val. */ append(field: string, value: string | number | string[]): void; /** * Remove header field. */ remove(field: string): void; /** * Get request Content-Type void of parameters such as "charset". */ get type(): { mineType?: keyof typeof mimeExtMap; suffixType?: string; rawType?: string; }; set type(val: { mineType?: keyof typeof mimeExtMap; suffixType?: string; rawType?: string; }); /** * Very similar to ctx.request.is(). * Check whether the response type is one of the supplied types. * This is particularly useful for creating middleware that manipulate responses. */ is(...types: string[]): string | false; /** * Perform a [302] redirect to url. * * The string "back" is special-cased to provide Referrer support, * when Referrer is not present alt or "/" is used. */ redirect(url: string, alt: string): void; /** * 设置 响应的 附件下载 Content-Disposition 头,并设置相应 Content-Type 头 * * refers: * https://github.com/jshttp/content-disposition * https://github.com/jshttp/content-disposition/blob/master/index.js */ attachment(filename: string): void; get headerSent(): boolean; /** * Return '' if header not exists * * Set the Last-Modified header as an appropriate UTC string. * You can either set it as a Date or date string. */ get lastModified(): Date | string; set lastModified(date: Date | string); /** * Set the ETag of a response including the wrapped "s. * Note that there is no corresponding response.etag getter. * * e.g. `crypto.createHash('md5').update(ctx.body).digest('hex')` */ get etag(): string; set etag(val: string); /** * 对向CDN缓存服务等 响应 说明区分某个字段的值做两份缓存(gzip|identity)? * * refers: https://imququ.com/post/vary-header-in-http.html */ vary(field: string): void; /** * Flush any set headers, and begin the body. */ flushHeaders(): void; } export { }