Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.0 #208

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
20 changes: 2 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ jobs:
strategy:
matrix:
name:
- Node.js 0.8
- Node.js 0.10
- Node.js 0.12
- io.js 1.x
Expand All @@ -32,11 +31,6 @@ jobs:
- Node.js 17.x

include:
- name: Node.js 0.8
node-version: "0.8"
npm-i: mocha@2.5.3 supertest@1.1.0
npm-rm: nyc

- name: Node.js 0.10
node-version: "0.10"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
Expand Down Expand Up @@ -75,11 +69,11 @@ jobs:

- name: Node.js 8.x
node-version: "8.16"
npm-i: mocha@7.2.0
npm-i: mocha@7.2.0 nyc@14.1.1

- name: Node.js 9.x
node-version: "9.11"
npm-i: mocha@7.2.0
npm-i: mocha@7.2.0 nyc@14.1.1

- name: Node.js 10.x
node-version: "10.24"
Expand Down Expand Up @@ -114,21 +108,11 @@ jobs:
shell: bash -eo pipefail -l {0}
run: |
nvm install --default ${{ matrix.node-version }}
if [[ "${{ matrix.node-version }}" == 0.* && "$(cut -d. -f2 <<< "${{ matrix.node-version }}")" -lt 10 ]]; then
nvm install --alias=npm 0.10
nvm use ${{ matrix.node-version }}
sed -i '1s;^.*$;'"$(printf '#!%q' "$(nvm which npm)")"';' "$(readlink -f "$(which npm)")"
npm config set strict-ssl false
fi
dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH"

- name: Configure npm
run: npm config set shrinkwrap false

- name: Remove npm module(s) ${{ matrix.npm-rm }}
run: npm rm --silent --save-dev ${{ matrix.npm-rm }}
if: matrix.npm-rm != ''

- name: Install npm module(s) ${{ matrix.npm-i }}
run: npm install --save-dev ${{ matrix.npm-i }}
if: matrix.npm-i != ''
Expand Down
23 changes: 23 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
1.0.0-beta.2 / 2024-03-04
=========================

* Changes from 0.18.0

1.0.0-beta.1 / 2022-02-04
=========================

* Drop support for Node.js 0.8
* Remove `hidden` option -- use `dotfiles` option
* Remove `from` alias to `root` -- use `root` directly
* Remove `send.etag()` -- use `etag` in `options`
* Remove `send.index()` -- use `index` in `options`
* Remove `send.maxage()` -- use `maxAge` in `options`
* Remove `send.root()` -- use `root` in `options`
* Use `mime-types` for file to content type mapping -- removed `send.mime`
* deps: debug@3.1.0
- Add `DEBUG_HIDE_DATE` environment variable
- Change timer to per-namespace instead of global
- Change non-TTY date format
- Remove `DEBUG_FD` environment variable support
- Support 256 namespace colors

0.18.0 / 2022-03-23
===================

Expand Down
27 changes: 10 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,6 @@ The `SendStream` is an event emitter and will emit the following events:
The `pipe` method is used to pipe the response into the Node.js HTTP response
object, typically `send(req, path, options).pipe(res)`.

### .mime

The `mime` export is the global instance of of the
[`mime` npm module](https://www.npmjs.com/package/mime).

This is used to configure the MIME types that are associated with file extensions
as well as other options for how to resolve the MIME type of a file (like the
default type to use for an unknown file extension).

## Error-handling

By default when no `error` listeners are present an automatic response will be
Expand Down Expand Up @@ -210,20 +201,22 @@ server.listen(3000)
### Custom file types

```js
var extname = require('path').extname
var http = require('http')
var parseUrl = require('parseurl')
var send = require('send')

// Default unknown types to text/plain
send.mime.default_type = 'text/plain'

// Add a custom type
send.mime.define({
'application/x-my-type': ['x-mt', 'x-mtt']
})

var server = http.createServer(function onRequest (req, res) {
send(req, parseUrl(req).pathname, { root: '/www/public' })
.on('headers', function (res, path) {
switch (extname(path)) {
case '.x-mt':
case '.x-mtt':
// custom type for these extensions
res.setHeader('Content-Type', 'application/x-my-type')
break
}
})
.pipe(res)
})

Expand Down
146 changes: 8 additions & 138 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@

var createError = require('http-errors')
var debug = require('debug')('send')
var deprecate = require('depd')('send')
var destroy = require('destroy')
var encodeUrl = require('encodeurl')
var escapeHtml = require('escape-html')
var etag = require('etag')
var fresh = require('fresh')
var fs = require('fs')
var mime = require('mime')
var mime = require('mime-types')
var ms = require('ms')
var onFinished = require('on-finished')
var parseRange = require('range-parser')
Expand Down Expand Up @@ -68,7 +67,6 @@ var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/
*/

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

/**
* Return a `SendStream` for `req` and `path`.
Expand Down Expand Up @@ -122,17 +120,6 @@ function SendStream (req, path, options) {
throw new TypeError('dotfiles option must be "allow", "deny", or "ignore"')
}

this._hidden = Boolean(opts.hidden)

if (opts.hidden !== undefined) {
deprecate('hidden: use dotfiles: \'' + (this._hidden ? 'allow' : 'ignore') + '\' instead')
}

// legacy support
if (opts.dotfiles === undefined) {
this._dotfiles = undefined
}

this._extensions = opts.extensions !== undefined
? normalizeList(opts.extensions, 'extensions option')
: []
Expand Down Expand Up @@ -160,10 +147,6 @@ function SendStream (req, path, options) {
this._root = opts.root
? resolve(opts.root)
: null

if (!this._root && opts.from) {
this.from(opts.from)
}
}

/**
Expand All @@ -172,90 +155,6 @@ function SendStream (req, path, options) {

util.inherits(SendStream, Stream)

/**
* Enable or disable etag generation.
*
* @param {Boolean} val
* @return {SendStream}
* @api public
*/

SendStream.prototype.etag = deprecate.function(function etag (val) {
this._etag = Boolean(val)
debug('etag %s', this._etag)
return this
}, 'send.etag: pass etag as option')

/**
* Enable or disable "hidden" (dot) files.
*
* @param {Boolean} path
* @return {SendStream}
* @api public
*/

SendStream.prototype.hidden = deprecate.function(function hidden (val) {
this._hidden = Boolean(val)
this._dotfiles = undefined
debug('hidden %s', this._hidden)
return this
}, 'send.hidden: use dotfiles option')

/**
* Set index `paths`, set to a falsy
* value to disable index support.
*
* @param {String|Boolean|Array} paths
* @return {SendStream}
* @api public
*/

SendStream.prototype.index = deprecate.function(function index (paths) {
var index = !paths ? [] : normalizeList(paths, 'paths argument')
debug('index %o', paths)
this._index = index
return this
}, 'send.index: pass index as option')

/**
* Set root `path`.
*
* @param {String} path
* @return {SendStream}
* @api public
*/

SendStream.prototype.root = function root (path) {
this._root = resolve(String(path))
debug('root %s', this._root)
return this
}

SendStream.prototype.from = deprecate.function(SendStream.prototype.root,
'send.from: pass root as option')

SendStream.prototype.root = deprecate.function(SendStream.prototype.root,
'send.root: pass root as option')

/**
* Set max-age to `maxAge`.
*
* @param {Number} maxAge
* @return {SendStream}
* @api public
*/

SendStream.prototype.maxage = deprecate.function(function maxage (maxAge) {
this._maxage = typeof maxAge === 'string'
? ms(maxAge)
: Number(maxAge)
this._maxage = !isNaN(this._maxage)
? Math.min(Math.max(0, this._maxage), MAX_MAXAGE)
: 0
debug('max-age %d', this._maxage)
return this
}, 'send.maxage: pass maxAge as option')

/**
* Emit error with `status`.
*
Expand Down Expand Up @@ -559,17 +458,8 @@ SendStream.prototype.pipe = function pipe (res) {

// dotfile handling
if (containsDotFile(parts)) {
var access = this._dotfiles

// legacy support
if (access === undefined) {
access = parts[parts.length - 1][0] === '.'
? (this._hidden ? 'allow' : 'ignore')
: 'allow'
}

debug('%s dotfile "%s"', access, path)
switch (access) {
debug('%s dotfile "%s"', this._dotfiles, path)
switch (this._dotfiles) {
case 'allow':
break
case 'deny':
Expand Down Expand Up @@ -608,7 +498,7 @@ SendStream.prototype.send = function send (path, stat) {
var ranges = req.headers.range
var offset = options.start || 0

if (headersSent(res)) {
if (res.headersSent) {
// impossible to send now
this.headersAlreadySent()
return
Expand Down Expand Up @@ -827,17 +717,11 @@ SendStream.prototype.type = function type (path) {

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

var type = mime.lookup(path)

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

var charset = mime.charsets.lookup(type)
var ext = extname(path)
var type = mime.contentType(ext) || 'application/octet-stream'

debug('content-type %s', type)
res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''))
res.setHeader('Content-Type', type)
}

/**
Expand Down Expand Up @@ -1019,7 +903,7 @@ function getHeaderNames (res) {
/**
* Determine if emitter has listeners of a given type.
*
* The way to do this check is done three different ways in Node.js >= 0.8
* The way to do this check is done three different ways in Node.js >= 0.10
* so this consolidates them into a minimal set using instance methods.
*
* @param {EventEmitter} emitter
Expand All @@ -1036,20 +920,6 @@ function hasListeners (emitter, type) {
return count > 0
}

/**
* Determine if the response headers have been sent.
*
* @param {object} res
* @returns {boolean}
* @private
*/

function headersSent (res) {
return typeof res.headersSent !== 'boolean'
? Boolean(res._header)
: res.headersSent
}

/**
* Normalize the index option into an array.
*
Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "send",
"description": "Better streaming static file server with Range and conditional-GET support",
"version": "0.18.0",
"version": "1.0.0-beta.2",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
"Douglas Christopher Wilson <doug@somethingdoug.com>",
Expand All @@ -16,15 +16,14 @@
"server"
],
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"debug": "3.1.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"mime-types": "~2.1.34",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
Expand All @@ -51,12 +50,13 @@
"index.js"
],
"engines": {
"node": ">= 0.8.0"
"node": ">= 0.10"
},
"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",
"version": "node scripts/version-history.js && git add HISTORY.md"
}
}