UNPKG

send-stream

Version:

Streaming file serving library with Range and conditional-GET support from file system or any streaming sources.

199 lines (198 loc) 8.99 kB
import type { ServerResponse } from 'node:http'; import { IncomingMessage } from 'node:http'; import type { IncomingHttpHeaders, Http2ServerResponse, ServerHttp2Stream } from 'node:http2'; import { Http2ServerRequest } from 'node:http2'; import type { Readable } from 'node:stream'; import { StreamResponse } from './response'; import type { ResponseHeaders } from './utils'; import { StreamRange } from './utils'; import type { StorageOptions, PrepareResponseOptions, StorageRequestHeaders, StorageInfo, StorageSendOptions } from './types'; /** * send-stream storage base class * @template Reference - reference type * @template AttachedData - attached data type */ export declare abstract class Storage<Reference, AttachedData> { /** * Default mime type or false */ readonly defaultMimeType: string | false; /** * Max ranges for multiple range GET requests */ readonly maxRanges: number; /** * Produces week tags when true */ readonly weakEtags: boolean; /** * Mime type lookup function */ readonly mimeTypeLookup: NonNullable<StorageOptions['mimeTypeLookup']>; /** * Mime type default charset function */ readonly mimeTypeDefaultCharset: NonNullable<StorageOptions['mimeTypeDefaultCharset']>; /** * Dynamic compression preferences or false */ readonly dynamicCompression: { encodingPreferences: ReadonlyMap<string, { order: number; }>; identityEncodingPreference: { order: number; }; } | false; /** * Mime type compressible function */ readonly mimeTypeCompressible: NonNullable<StorageOptions['mimeTypeCompressible']>; /** * Minimum length to produce compressed content */ readonly dynamicCompressionMinLength: number; /** * Create storage * @param opts - storage options */ constructor(opts?: StorageOptions); /** * Create last-mofified header value from storage information (uses mtimeMs) * @param storageInfo - storage information * @returns last-mofified header */ createLastModified(storageInfo: StorageInfo<AttachedData>): string | false; /** * Create etag header value from storage information (uses mtimeMs, size and contentEncoding) * @param storageInfo - storage information * @returns etag header */ createEtag(storageInfo: StorageInfo<AttachedData>): string | false; /** * Create cache-control header value from storage information (return always public, max-age=0 unless overriden) * @param storageInfo - storage information * @returns cache-control header */ createCacheControl(storageInfo: StorageInfo<AttachedData>): string | false; /** * Create mime type for content-type header value from storage information * @param storageInfo - storage information (unused unless overriden) * @returns mime type */ createMimeType(storageInfo: StorageInfo<AttachedData>): string | false; /** * Create charset that will be appended with mime type into content-type header * @param storageInfo - storage information (unused unless overriden) * @param mimeType - mime type * @returns charset */ createMimeTypeCharset(storageInfo: StorageInfo<AttachedData>, mimeType: string): string | false; /** * Create content-disposition header type from storage information (return always inline unless overriden) * @param storageInfo - storage information (unused unless overriden) * @returns content-disposition header type */ createContentDispositionType(storageInfo: StorageInfo<AttachedData>): 'inline' | 'attachment' | undefined; /** * Create content-disposition header filename from storage information * (return always the original filename unless overriden) * @param storageInfo - storage information * @returns content-disposition header filename */ createContentDispositionFilename(storageInfo: StorageInfo<AttachedData>): string | undefined; /** * Prepare to send file * @param reference - file reference * @param req - request headers or request objects * @param [opts] - options * @returns status, response headers and body to use * @throws when method is incorrect or when storage can not create the storage stream */ prepareResponse(reference: Reference, req: IncomingMessage | Http2ServerRequest | IncomingHttpHeaders, opts?: PrepareResponseOptions): Promise<StreamResponse<AttachedData>>; /** * Send file directly to response * @param reference - file reference * @param req - request headers or request objects * @param res - http response * @param [opts] - options * @throws when method is incorrect or when storage can not create the storage stream */ send(reference: Reference, req: IncomingMessage | Http2ServerRequest | IncomingHttpHeaders, res: ServerResponse | Http2ServerResponse | ServerHttp2Stream, opts?: StorageSendOptions): Promise<void>; /** * Create compressed stream * (for gzip / brotli encodings only but this method can be overidden to eventually implement other encodings) * @param stream - stream to compress * @param contentEncoding - 'br' for brotli encoding or 'gzip' for gzip encoding, other values are not supported * @param expectedSize - expected stream size * @returns compressed stream * @throws if content encoding is not supported */ createCompressedStream(stream: Readable, contentEncoding: string, expectedSize?: number): Readable; /** * Create Method Not Allowed error response * @param isHeadMethod - true if HEAD method is used * @param allowedMethods - allowed methods for Allow header * @returns Method Not Allowed response */ createMethodNotAllowedError(isHeadMethod: boolean, allowedMethods: readonly string[]): StreamResponse<AttachedData>; /** * Create storage error response (Not Found response usually) * @param isHeadMethod - true if HEAD method is used * @param error - the error causing this response * @returns the error response */ createStorageError(isHeadMethod: boolean, error: unknown): StreamResponse<AttachedData>; /** * Create Not Modified response * @param responseHeaders - response headers * @param storageInfo - the current storage info * @returns the Not Modified response */ createNotModifiedResponse(responseHeaders: ResponseHeaders, storageInfo: StorageInfo<AttachedData>): StreamResponse<AttachedData>; /** * Create the Precondition Failed error response * @param isHeadMethod - true if HEAD method is used * @param storageInfo - the current storage info * @returns the Precondition Failed error response */ createPreconditionFailedError(isHeadMethod: boolean, storageInfo: StorageInfo<AttachedData>): StreamResponse<AttachedData>; /** * Create the Range Not Satisfiable error response * @param isHeadMethod - true if HEAD method is used * @param size - size of content for Content-Range header * @param storageInfo - the current storage info * @returns the Range Not Satisfiable error response */ createRangeNotSatisfiableError(isHeadMethod: boolean, size: number, storageInfo: StorageInfo<AttachedData>): StreamResponse<AttachedData>; /** * Create the successful OK (200) or Partial Content (206) response * (the http code could also be the one set in parameters) * @param statusCode - 200 or 206 or the statusCode set in parameters * @param responseHeaders - the response headers * @param stream - the content stream * @param storageInfo - the current storage info * @returns the successful response */ createSuccessfulResponse(statusCode: number, responseHeaders: ResponseHeaders, stream: Readable, storageInfo: StorageInfo<AttachedData>): StreamResponse<AttachedData>; /** * Open file and retrieve storage information (filename, modification date, size, ...) * @param reference - file reference * @param requestHeaders - request headers * @returns StorageInfo object */ abstract open(reference: Reference, requestHeaders: StorageRequestHeaders): Promise<StorageInfo<AttachedData>>; /** * Create readable stream from storage information * @param storageInfo - storage information * @param range - range to use or undefined if size is unknown * @param autoClose - true if stream should close itself * @returns readable stream */ abstract createReadableStream(storageInfo: StorageInfo<AttachedData>, range: StreamRange | undefined, autoClose: boolean): Readable; /** * Close storage information (if needed) * @param storageInfo - storage information */ abstract close(storageInfo: StorageInfo<AttachedData>): Promise<void>; }