Skip to content

Commit

Permalink
add types, nodenext, upgrade mime
Browse files Browse the repository at this point in the history
  • Loading branch information
Uzlopak committed Jan 12, 2023
1 parent e5ebad0 commit ff69d86
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 22 deletions.
33 changes: 21 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,6 @@ var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1000 // 1 year

var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/

/**
* Module exports.
* @public
*/

module.exports = send
module.exports.mime = mime

/**
* Return a `SendStream` for `req` and `path`.
*
Expand Down Expand Up @@ -814,6 +806,9 @@ SendStream.prototype.stream = function stream (path, options) {
})
}

const utf8MimeTypeRE = /^text\/|^application\/(javascript|json)/
const isUtf8MimeType = utf8MimeTypeRE.test.bind(utf8MimeTypeRE)

/**
* Set content-type based on `path`
* if it hasn't been explicitly set.
Expand All @@ -827,17 +822,19 @@ SendStream.prototype.type = function type (path) {

if (res.getHeader('Content-Type')) return

var type = mime.lookup(path)
var type = mime.getType(path) || mime.default_type

if (!type) {
debug('no content-type')
return
}

var charset = mime.charsets.lookup(type)

debug('content-type %s', type)
res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''))
if (isUtf8MimeType(type)) {
res.setHeader('Content-Type', type + '; charset=UTF-8')
} else {
res.setHeader('Content-Type', type)
}
}

/**
Expand Down Expand Up @@ -1141,3 +1138,15 @@ function setHeaders (res, headers) {
res.setHeader(key, headers[key])
}
}

/**
* Module exports.
* @public
*/

module.exports = send
module.exports.default = send
module.exports.send = send

module.exports.isUtf8MimeType = isUtf8MimeType
module.exports.mime = mime
18 changes: 8 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"James Wyatt Cready <jcready@gmail.com>",
"Jesús Leganés Combarro <piranna@gmail.com>"
],
"main": "index.js",
"types": "types/index.d.ts",
"license": "MIT",
"repository": "fastify/send",
"keywords": [
Expand All @@ -24,13 +26,14 @@
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"mime": "^3.0.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
},
"devDependencies": {
"@types/node": "^18.11.18",
"after": "0.8.2",
"eslint": "7.32.0",
"eslint-config-standard": "14.1.1",
Expand All @@ -41,22 +44,17 @@
"eslint-plugin-standard": "4.1.0",
"mocha": "9.2.2",
"nyc": "15.1.0",
"supertest": "6.2.2"
"supertest": "6.2.2",
"tsd": "^0.25.0"
},
"files": [
"HISTORY.md",
"LICENSE",
"README.md",
"SECURITY.md",
"index.js"
],
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"lint": "eslint .",
"test": "mocha --check-leaks --reporter spec --bail",
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test"
"test-cov": "nyc --reporter=html --reporter=text npm test",
"test:typescript": "tsd"
}
}
248 changes: 248 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
// Definitions by: Mike Jerred <https://github.com/MikeJerred>
// Piotr Błażejewicz <https://github.com/peterblazejewicz>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

/// <reference types="node" />

import * as stream from "stream";
import * as fs from "fs";

/**
* Create a new SendStream for the given path to send to a res.
* The req is the Node.js HTTP request and the path is a urlencoded path to send (urlencoded, not the actual file-system path).
*/
declare function send(req: stream.Readable, path: string, options?: send.SendOptions): send.SendStream;

type Send = typeof send;

declare class Mime {
constructor(typeMap: TypeMap, ...mimes: TypeMap[]);

getType(path: string): string | null;
getExtension(mime: string): string | null;
define(typeMap: TypeMap, force?: boolean): void;
}

interface TypeMap {
[key: string]: string[];
}

declare namespace send {
export const mime: Mime;
export const isUtf8MimeType: (value: string) => boolean;

export interface SendOptions {
/**
* Enable or disable accepting ranged requests, defaults to true.
* Disabling this will not send Accept-Ranges and ignore the contents of the Range request header.
*/
acceptRanges?: boolean | undefined;

/**
* Enable or disable setting Cache-Control response header, defaults to true.
* Disabling this will ignore the maxAge option.
*/
cacheControl?: boolean | undefined;

/**
* Set how "dotfiles" are treated when encountered.
* A dotfile is a file or directory that begins with a dot (".").
* Note this check is done on the path itself without checking if the path actually exists on the disk.
* If root is specified, only the dotfiles above the root are checked (i.e. the root itself can be within a dotfile when when set to "deny").
* 'allow' No special treatment for dotfiles.
* 'deny' Send a 403 for any request for a dotfile.
* 'ignore' Pretend like the dotfile does not exist and 404.
* The default value is similar to 'ignore', with the exception that this default will not ignore the files within a directory that begins with a dot, for backward-compatibility.
*/
dotfiles?: "allow" | "deny" | "ignore" | undefined;

/**
* Byte offset at which the stream ends, defaults to the length of the file minus 1.
* The end is inclusive in the stream, meaning end: 3 will include the 4th byte in the stream.
*/
end?: number | undefined;

/**
* Enable or disable etag generation, defaults to true.
*/
etag?: boolean | undefined;

/**
* If a given file doesn't exist, try appending one of the given extensions, in the given order.
* By default, this is disabled (set to false).
* An example value that will serve extension-less HTML files: ['html', 'htm'].
* This is skipped if the requested file already has an extension.
*/
extensions?: string[] | string | boolean | undefined;

/**
* Enable or disable the immutable directive in the Cache-Control response header, defaults to false.
* If set to true, the maxAge option should also be specified to enable caching.
* The immutable directive will prevent supported clients from making conditional requests during the life of the maxAge option to check if the file has changed.
* @default false
*/
immutable?: boolean | undefined;

/**
* By default send supports "index.html" files, to disable this set false or to supply a new index pass a string or an array in preferred order.
*/
index?: string[] | string | boolean | undefined;

/**
* Enable or disable Last-Modified header, defaults to true.
* Uses the file system's last modified value.
*/
lastModified?: boolean | undefined;

/**
* Provide a max-age in milliseconds for http caching, defaults to 0.
* This can also be a string accepted by the ms module.
*/
maxAge?: string | number | undefined;

/**
* Serve files relative to path.
*/
root?: string | undefined;

/**
* Byte offset at which the stream starts, defaults to 0.
* The start is inclusive, meaning start: 2 will include the 3rd byte in the stream.
*/
start?: number | undefined;
}

export interface SendStream extends stream.Stream {
/**
* @deprecated pass etag as option
* Enable or disable etag generation.
*/
etag(val: boolean): SendStream;

/**
* @deprecated use dotfiles option
* Enable or disable "hidden" (dot) files.
*/
hidden(val: boolean): SendStream;

/**
* @deprecated pass index as option
* Set index `paths`, set to a falsy value to disable index support.
*/
index(paths: string[] | string): SendStream;

/**
* @deprecated pass root as option
* Set root `path`.
*/
root(paths: string): SendStream;

/**
* @deprecated pass root as option
* Set root `path`.
*/
from(paths: string): SendStream;

/**
* @deprecated pass maxAge as option
* Set max-age to `maxAge`.
*/
maxage(maxAge: string | number): SendStream;

/**
* Emit error with `status`.
*/
error(status: number, error?: Error): void;

/**
* Check if the pathname ends with "/".
*/
hasTrailingSlash(): boolean;

/**
* Check if this is a conditional GET request.
*/
isConditionalGET(): boolean;

/**
* Strip content-* header fields.
*/
removeContentHeaderFields(): void;

/**
* Respond with 304 not modified.
*/
notModified(): void;

/**
* Raise error that headers already sent.
*/
headersAlreadySent(): void;

/**
* Check if the request is cacheable, aka responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}).
*/
isCachable(): boolean;

/**
* Handle stat() error.
*/
onStatError(error: Error): void;

/**
* Check if the cache is fresh.
*/
isFresh(): boolean;

/**
* Check if the range is fresh.
*/
isRangeFresh(): boolean;

/**
* Redirect to path.
*/
redirect(path: string): void;

/**
* Pipe to `res`.
*/
pipe<T extends NodeJS.WritableStream>(res: T): T;

/**
* Transfer `path`.
*/
send(path: string, stat?: fs.Stats): void;

/**
* Transfer file for `path`.
*/
sendFile(path: string): void;

/**
* Transfer index for `path`.
*/
sendIndex(path: string): void;

/**
* Transfer index for `path`.
*/
stream(path: string, options?: {}): void;

/**
* Set content-type based on `path` if it hasn't been explicitly set.
*/
type(path: string): void;

/**
* Set response header fields, most fields may be pre-defined.
*/
setHeader(path: string, stat: fs.Stats): void;
}

export const send: Send

export { send as default }
}

export = send;
Loading

0 comments on commit ff69d86

Please sign in to comment.