Commit 2dd5453a authored by Leo Iannacone's avatar Leo Iannacone

update external libraries

parent 09129e47
1.4.1 / 2015-02-15
==================
* deps: accepts@~1.2.4
- deps: mime-types@~2.0.9
- deps: negotiator@0.5.1
1.4.0 / 2015-02-01
==================
* Prefer `gzip` over `deflate` on the server
- Not all clients agree on what "deflate" coding means
1.3.1 / 2015-01-31
==================
* deps: accepts@~1.2.3
- deps: mime-types@~2.0.8
* deps: compressible@~2.0.2
- deps: mime-db@'>= 1.1.2 < 2'
1.3.0 / 2014-12-30
==================
* Export the default `filter` function for wrapping
* deps: accepts@~1.2.2
- deps: mime-types@~2.0.7
- deps: negotiator@0.5.0
* deps: debug@~2.1.1
1.2.2 / 2014-12-10
==================
* Fix `.end` to only proxy to `.end`
- Fixes an issue with Node.js 0.11.14
* deps: accepts@~1.1.4
- deps: mime-types@~2.0.4
1.2.1 / 2014-11-23
==================
* deps: accepts@~1.1.3
- deps: mime-types@~2.0.3
1.2.0 / 2014-10-16
==================
* deps: debug@~2.1.0
- Implement `DEBUG_FD` env variable support
1.1.2 / 2014-10-15
==================
* deps: accepts@~1.1.2
- Fix error when media type has invalid parameter
- deps: negotiator@0.4.9
1.1.1 / 2014-10-12
==================
* deps: accepts@~1.1.1
- deps: mime-types@~2.0.2
- deps: negotiator@0.4.8
* deps: compressible@~2.0.1
- deps: mime-db@1.x
1.1.0 / 2014-09-07
==================
* deps: accepts@~1.1.0
* deps: compressible@~2.0.0
* deps: debug@~2.0.0
1.0.11 / 2014-08-10
===================
* deps: on-headers@~1.0.0
* deps: vary@~1.0.0
1.0.10 / 2014-08-05
===================
* deps: compressible@~1.1.1
- Fix upper-case Content-Type characters prevent compression
1.0.9 / 2014-07-20
==================
* Add `debug` messages
* deps: accepts@~1.0.7
- deps: negotiator@0.4.7
1.0.8 / 2014-06-20
==================
* deps: accepts@~1.0.5
- use `mime-types`
1.0.7 / 2014-06-11
==================
* use vary module for better `Vary` behavior
* deps: accepts@1.0.3
* deps: compressible@1.1.0
1.0.6 / 2014-06-03
==================
* fix regression when negotiation fails
1.0.5 / 2014-06-03
==================
* fix listeners for delayed stream creation
- fixes regression for certain `stream.pipe(res)` situations
1.0.4 / 2014-06-03
==================
* fix adding `Vary` when value stored as array
* fix back-pressure behavior
* fix length check for `res.end`
1.0.3 / 2014-05-29
==================
* use `accepts` for negotiation
* use `on-headers` to handle header checking
* deps: bytes@1.0.0
1.0.2 / 2014-04-29
==================
* only version compatible with node.js 0.8
* support headers given to `res.writeHead`
* deps: bytes@0.3.0
* deps: negotiator@0.4.3
1.0.1 / 2014-03-08
==================
* bump negotiator
* use compressible
* use .headersSent (drops 0.8 support)
* handle identity;q=0 case
(The MIT License)
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
Copyright (c) 2014 Douglas Christopher Wilson <doug@somethingdoug.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# compression
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
[![Gratipay][gratipay-image]][gratipay-url]
Node.js compression middleware.
The following compression codings are supported:
- deflate
- gzip
## Install
```bash
$ npm install compression
```
## API
```js
var compression = require('compression')
```
### compression([options])
Returns the compression middleware using the given `options`.
#### Options
`compression()` accepts these properties in the options object. In addition to
those listed below, [zlib](http://nodejs.org/api/zlib.html) options may be
passed in to the options object.
##### chunkSize
The default value is `zlib.Z_DEFAULT_CHUNK`, or `16384`.
See [Node.js documentation](http://nodejs.org/api/zlib.html#zlib_memory_usage_tuning)
regarding the usage.
##### filter
A function to decide if the response should be considered for compression.
This function is called as `filter(req, res)` and is expected to return
`true` to consider the response for compression, or `false` to not compress
the response.
The default filter function uses the [compressible](https://www.npmjs.com/package/compressible)
module to determine if `res.getHeader('Content-Type')` is compressible.
##### level
The level of zlib compression to apply to responses. A higher level will result
in better compression, but will take longer to complete. A lower level will
result in less compression, but will be much faster.
This is an integer in the range of `0` (no compression) to `9` (maximum
compression). The special value `-1` can be used to mean the "default
compression level", which is a default compromise between speed and
compression (currently equivalent to level 6).
- `-1` Default compression level (also `zlib.Z_DEFAULT_COMPRESSION`).
- `0` No compression (also `zlib.Z_NO_COMPRESSION`).
- `1` Fastest compression (also `zlib.Z_BEST_SPEED`).
- `2`
- `3`
- `4`
- `5`
- `6` (currently what `zlib.Z_DEFAULT_COMPRESSION` points to).
- `7`
- `8`
- `9` Best compression (also `zlib.Z_BEST_COMPRESSION`).
The default value is `zlib.Z_DEFAULT_COMPRESSION`, or `-1`.
**Note** in the list above, `zlib` is from `zlib = require('zlib')`.
##### memLevel
This specifies how much memory should be allocated for the internal compression
state and is an integer in the range of `1` (minimum level) and `9` (maximum
level).
The default value is `zlib.Z_DEFAULT_MEMLEVEL`, or `8`.
See [Node.js documentation](http://nodejs.org/api/zlib.html#zlib_memory_usage_tuning)
regarding the usage.
##### strategy
This is used to tune the compression algorithm. This value only affects the
compression ratio, not the correctness of the compressed output, even if it
is not set appropriately.
- `zlib.Z_DEFAULT_STRATEGY` Use for normal data.
- `zlib.Z_FILTERED` Use for data produced by a filter (or predictor).
Filtered data consists mostly of small values with a somewhat random
distribution. In this case, the compression algorithm is tuned to
compress them better. The effect is to force more Huffman coding and less
string matching; it is somewhat intermediate between `zlib.Z_DEFAULT_STRATEGY`
and `zlib.Z_HUFFMAN_ONLY`.
- `zlib.Z_FIXED` Use to prevent the use of dynamic Huffman codes, allowing
for a simpler decoder for special applications.
- `zlib.Z_HUFFMAN_ONLY` Use to force Huffman encoding only (no string match).
- `zlib.Z_RLE` Use to limit match distances to one (run-length encoding).
This is designed to be almost as fast as `zlib.Z_HUFFMAN_ONLY`, but give
better compression for PNG image data.
**Note** in the list above, `zlib` is from `zlib = require('zlib')`.
##### threshold
The byte threshold for the response body size before compression is considered
for the response, defaults to `1kb`. This is a number of bytes, any string
accepted by the [bytes](https://www.npmjs.com/package/bytes) module, or `false`.
##### windowBits
The default value is `zlib.Z_DEFAULT_WINDOWBITS`, or `15`.
See [Node.js documentation](http://nodejs.org/api/zlib.html#zlib_memory_usage_tuning)
regarding the usage.
#### .filter
The default `filter` function. This is used to construct a custom filter
function that is an extension of the default function.
```js
app.use(compression({filter: shouldCompress}))
function shouldCompress(req, res) {
if (req.headers['x-no-compression']) {
// don't compress responses with this request header
return false
}
// fallback to standard filter function
return compression.filter(req, res)
}
```
### res.flush
This module adds a `res.flush()` method to force the partially-compressed
response to be flushed to the client.
## Examples
### express/connect
When using this module with express or connect, simply `app.use` the module as
high as you like. Requests that pass through the middleware will be compressed.
```js
var compression = require('compression')
var express = require('express')
var app = express()
// compress all requests
app.use(compression())
// add all routes
```
### Server-Sent Events
Because of the nature of compression this module does not work out of the box
with server-sent events. To compress content, a window of the output needs to
be buffered up in order to get good compression. Typically when using server-sent
events, there are certain block of data that need to reach the client.
You can achieve this by calling `res.flush()` when you need the data written to
actually make it to the client.
```js
var compression = require('compression')
var express = require('express')
var app = express()
// compress responses
app.use(compression())
// server-sent event stream
app.get('/events', function (req, res) {
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
// send a ping approx every 2 seconds
var timer = setInterval(function () {
res.write('data: ping\n\n')
// !!! this is the important part
res.flush()
}, 2000)
res.on('close', function () {
clearInterval(timer)
})
})
```
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/compression.svg?style=flat
[npm-url]: https://npmjs.org/package/compression
[travis-image]: https://img.shields.io/travis/expressjs/compression.svg?style=flat
[travis-url]: https://travis-ci.org/expressjs/compression
[coveralls-image]: https://img.shields.io/coveralls/expressjs/compression.svg?style=flat
[coveralls-url]: https://coveralls.io/r/expressjs/compression?branch=master
[downloads-image]: https://img.shields.io/npm/dm/compression.svg?style=flat
[downloads-url]: https://npmjs.org/package/compression
[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg?style=flat
[gratipay-url]: https://www.gratipay.com/dougwilson/
/*!
* compression
* Copyright(c) 2010 Sencha Inc.
* Copyright(c) 2011 TJ Holowaychuk
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
* @private
*/
var accepts = require('accepts')
var bytes = require('bytes')
var compressible = require('compressible')
var debug = require('debug')('compression')
var onHeaders = require('on-headers')
var vary = require('vary')
var zlib = require('zlib')
/**
* Module exports.
*/
module.exports = compression
module.exports.filter = shouldCompress
/**
* Compress response data with gzip / deflate.
*
* @param {Object} options
* @return {Function} middleware
* @public
*/
function compression(options) {
var opts = options || {}
var filter = opts.filter || shouldCompress
var threshold = typeof opts.threshold === 'string'
? bytes(opts.threshold)
: opts.threshold
if (threshold == null) {
threshold = 1024
}
return function compression(req, res, next){
var compress = true
var listeners = []
var write = res.write
var on = res.on
var end = res.end
var stream
// see #8
req.on('close', function(){
res.write = res.end = noop
});
// flush is noop by default
res.flush = noop;
// proxy
res.write = function(chunk, encoding){
if (!this._header) {
// if content-length is set and is lower
// than the threshold, don't compress
var len = Number(res.getHeader('Content-Length'))
checkthreshold(len)
this._implicitHeader();
}
return stream
? stream.write(new Buffer(chunk, encoding))
: write.call(res, chunk, encoding);
};
res.end = function(chunk, encoding){
var len
if (chunk) {
len = Buffer.isBuffer(chunk)
? chunk.length
: Buffer.byteLength(chunk, encoding)
}
if (!this._header) {
len = Number(this.getHeader('Content-Length')) || len
checkthreshold(len)
this._implicitHeader()
}
return stream
? stream.end(chunk, encoding)
: end.call(res, chunk, encoding)
};
res.on = function(type, listener){
if (!listeners || type !== 'drain') {
return on.call(this, type, listener)
}
if (stream) {
return stream.on(type, listener)
}
// buffer listeners for future stream
listeners.push([type, listener])
return this
}
function checkthreshold(len) {
if (compress && len < threshold) {
debug('size below threshold')
compress = false
}
}
function nocompress(msg) {
debug('no compression' + (msg ? ': ' + msg : ''))
addListeners(res, on, listeners)
listeners = null
}
onHeaders(res, function(){
// determine if request is filtered
if (!filter(req, res)) {
nocompress('filtered')
return
}
// vary
vary(res, 'Accept-Encoding')
if (!compress) {
nocompress()
return
}
var encoding = res.getHeader('Content-Encoding') || 'identity';
// already encoded
if ('identity' !== encoding) {
nocompress('already encoded')
return
}
// head
if ('HEAD' === req.method) {
nocompress('HEAD request')
return
}
// compression method
var accept = accepts(req)
var method = accept.encoding(['gzip', 'deflate', 'identity'])
// we really don't prefer deflate
if (method === 'deflate' && accept.encoding(['gzip'])) {
method = accept.encoding(['gzip', 'identity'])
}
// negotiation failed
if (!method || method === 'identity') {
nocompress('not acceptable')
return
}
// compression stream
debug('%s compression', method)
stream = method === 'gzip'
? zlib.createGzip(opts)
: zlib.createDeflate(opts)
// add bufferred listeners to stream
addListeners(stream, stream.on, listeners)
// overwrite the flush method
res.flush = function(){
stream.flush();
}
// header fields
res.setHeader('Content-Encoding', method);
res.removeHeader('Content-Length');
// compression
stream.on('data', function(chunk){
if (write.call(res, chunk) === false) {
stream.pause()
}
});
stream.on('end', function(){
end.call(res);
});
on.call(res, 'drain', function() {
stream.resume()
});
});
next();
};
}
/**
* Add bufferred listeners to stream
* @private
*/
function addListeners(stream, on, listeners) {
for (var i = 0; i < listeners.length; i++) {
on.apply(stream, listeners[i])
}
}
/**
* No-operation function
* @private
*/
function noop(){}
/**
* Default filter function.
* @private
*/
function shouldCompress(req, res) {
var type = res.getHeader('Content-Type')
if (type === undefined || !compressible(type)) {
debug('%s not compressible', type)
return false
}
return true
}
1.2.4 / 2015-02-14
==================
* Support Node.js 0.6
* deps: mime-types@~2.0.9
- deps: mime-db@~1.7.0
* deps: negotiator@0.5.1
- Fix preference sorting to be stable for long acceptable lists
1.2.3 / 2015-01-31
==================
* deps: mime-types@~2.0.8
- deps: mime-db@~1.6.0
1.2.2 / 2014-12-30
==================
* deps: mime-types@~2.0.7
- deps: mime-db@~1.5.0
1.2.1 / 2014-12-30
==================
* deps: mime-types@~2.0.5
- deps: mime-db@~1.3.1
1.2.0 / 2014-12-19
==================
* deps: negotiator@0.5.0
- Fix list return order when large accepted list
- Fix missing identity encoding when q=0 exists
- Remove dynamic building of Negotiator class
1.1.4 / 2014-12-10
==================
* deps: mime-types@~2.0.4
- deps: mime-db@~1.3.0
1.1.3 / 2014-11-09
==================
* deps: mime-types@~2.0.3
- deps: mime-db@~1.2.0
1.1.2 / 2014-10-14
==================
* deps: negotiator@0.4.9
- Fix error when media type has invalid parameter
1.1.1 / 2014-09-28
==================
* deps: mime-types@~2.0.2
- deps: mime-db@~1.1.0
* deps: negotiator@0.4.8
- Fix all negotiations to be case-insensitive
- Stable sort preferences of same quality according to client order
1.1.0 / 2014-09-02
==================
* update `mime-types`
1.0.7 / 2014-07-04
==================
* Fix wrong type returned from `type` when match after unknown extension
1.0.6 / 2014-06-24
==================
* deps: negotiator@0.4.7
1.0.5 / 2014-06-20
==================
* fix crash when unknown extension given
1.0.4 / 2014-06-19
==================
* use `mime-types`
1.0.3 / 2014-06-11
==================
* deps: negotiator@0.4.6
- Order by specificity when quality is the same
1.0.2 / 2014-05-29
==================
* Fix interpretation when header not in request
* deps: pin negotiator@0.4.5
1.0.1 / 2014-01-18
==================
* Identity encoding isn't always acceptable
* deps: negotiator@~0.4.0
1.0.0 / 2013-12-27
==================
* Genesis
(The MIT License)
Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# accepts
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). Extracted from [koa](https://www.npmjs.com/package/koa) for general use.
In addition to negotiator, it allows:
- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` as well as `('text/html', 'application/json')`.
- Allows type shorthands such as `json`.
- Returns `false` when no types match
- Treats non-existent headers as `*`
## Installation
```sh
npm install accepts
```
## API
```js
var accepts = require('accepts')
```
### accepts(req)
Create a new `Accepts` object for the given `req`.
#### .charset(charsets)
Return the first accepted charset. If nothing in `charsets` is accepted,
then `false` is returned.
#### .charsets()
Return the charsets that the request accepts, in the order of the client's
preference (most preferred first).
#### .encoding(encodings)
Return the first accepted encoding. If nothing in `encodings` is accepted,
then `false` is returned.
#### .encodings()
Return the encodings that the request accepts, in the order of the client's
preference (most preferred first).
#### .language(languages)
Return the first accepted language. If nothing in `languages` is accepted,
then `false` is returned.
#### .languages()
Return the languages that the request accepts, in the order of the client's
preference (most preferred first).
#### .type(types)
Return the first accepted type (and it is returned as the same text as what
appears in the `types` array). If nothing in `types` is accepted, then `false`
is returned.
The `types` array can contain full MIME types or file extensions. Any value
that is not a full MIME types is passed to `require('mime-types').lookup`.
#### .types()
Return the types that the request accepts, in the order of the client's
preference (most preferred first).
## Examples
### Simple type negotiation
This simple example shows how to use `accepts` to return a different typed
respond body based on what the client wants to accept. The server lists it's
preferences in order and will get back the best match between the client and
server.
```js
var accepts = require('accepts')
var http = require('http')
function app(req, res) {
var accept = accepts(req)
// the order of this list is significant; should be server preferred order
switch(accept.type(['json', 'html'])) {
case 'json':
res.setHeader('Content-Type', 'application/json')
res.write('{"hello":"world!"}')
break
case 'html':
res.setHeader('Content-Type', 'text/html')
res.write('<b>hello, world!</b>')
break
default:
// the fallback is text/plain, so no need to specify it above
res.setHeader('Content-Type', 'text/plain')
res.write('hello, world!')
break
}
res.end()
}
http.createServer(app).listen(3000)
```
You can test this out with the cURL program:
```sh
curl -I -H'Accept: text/html' http://localhost:3000/
```
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/accepts.svg?style=flat
[npm-url]: https://npmjs.org/package/accepts
[node-version-image]: https://img.shields.io/node/v/accepts.svg?style=flat
[node-version-url]: http://nodejs.org/download/
[travis-image]: https://img.shields.io/travis/jshttp/accepts.svg?style=flat
[travis-url]: https://travis-ci.org/jshttp/accepts
[coveralls-image]: https://img.shields.io/coveralls/jshttp/accepts.svg?style=flat
[coveralls-url]: https://coveralls.io/r/jshttp/accepts
[downloads-image]: https://img.shields.io/npm/dm/accepts.svg?style=flat
[downloads-url]: https://npmjs.org/package/accepts
var Negotiator = require('negotiator')
var mime = require('mime-types')
var slice = [].slice
module.exports = Accepts
function Accepts(req) {
if (!(this instanceof Accepts))
return new Accepts(req)
this.headers = req.headers
this.negotiator = Negotiator(req)
}
/**
* 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" 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
* this.types('html');
* // => "html"
*
* // Accept: text/*, application/json
* this.types('html');
* // => "html"
* this.types('text/html');
* // => "text/html"
* this.types('json', 'text');
* // => "json"
* this.types('application/json');
* // => "application/json"
*
* // Accept: text/*, application/json
* this.types('image/png');
* this.types('png');
* // => undefined
*
* // Accept: text/*;q=.5, application/json
* this.types(['html', 'json']);
* this.types('html', 'json');
* // => "json"
*
* @param {String|Array} type(s)...
* @return {String|Array|Boolean}
* @api public
*/
Accepts.prototype.type =
Accepts.prototype.types = function (types) {
if (!Array.isArray(types)) types = slice.call(arguments);
var n = this.negotiator;
if (!types.length) return n.mediaTypes();
if (!this.headers.accept) return types[0];
var mimes = types.map(extToMime);
var accepts = n.mediaTypes(mimes.filter(validMime));
var first = accepts[0];
if (!first) return false;
return types[mimes.indexOf(first)];
}
/**
* Return accepted encodings or best fit based on `encodings`.
*
* Given `Accept-Encoding: gzip, deflate`
* an array sorted by quality is returned:
*
* ['gzip', 'deflate']
*
* @param {String|Array} encoding(s)...
* @return {String|Array}
* @api public
*/
Accepts.prototype.encoding =
Accepts.prototype.encodings = function (encodings) {
if (!Array.isArray(encodings)) encodings = slice.call(arguments);
var n = this.negotiator;
if (!encodings.length) return n.encodings();
return n.encodings(encodings)[0] || false;
}
/**
* Return accepted charsets or best fit based on `charsets`.
*
* Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
* an array sorted by quality is returned:
*
* ['utf-8', 'utf-7', 'iso-8859-1']
*
* @param {String|Array} charset(s)...
* @return {String|Array}
* @api public
*/
Accepts.prototype.charset =
Accepts.prototype.charsets = function (charsets) {
if (!Array.isArray(charsets)) charsets = [].slice.call(arguments);
var n = this.negotiator;
if (!charsets.length) return n.charsets();
if (!this.headers['accept-charset']) return charsets[0];
return n.charsets(charsets)[0] || false;
}
/**
* Return accepted languages or best fit based on `langs`.
*
* Given `Accept-Language: en;q=0.8, es, pt`
* an array sorted by quality is returned:
*
* ['es', 'pt', 'en']
*
* @param {String|Array} lang(s)...
* @return {Array|String}
* @api public
*/
Accepts.prototype.lang =
Accepts.prototype.langs =
Accepts.prototype.language =
Accepts.prototype.languages = function (langs) {
if (!Array.isArray(langs)) langs = slice.call(arguments);
var n = this.negotiator;
if (!langs.length) return n.languages();
if (!this.headers['accept-language']) return langs[0];
return n.languages(langs)[0] || false;
}
/**
* Convert extnames to mime.
*
* @param {String} type
* @return {String}
* @api private
*/
function extToMime(type) {
if (~type.indexOf('/')) return type;
return mime.lookup(type);
}
/**
* Check if mime is valid.
*
* @param {String} type
* @return {String}
* @api private
*/
function validMime(type) {
return typeof type === 'string';
}
2.0.9 / 2015-02-09
==================
* deps: mime-db@~1.7.0
- Add new mime types
- Community extensions ownership transferred from `node-mime`
2.0.8 / 2015-01-29
==================
* deps: mime-db@~1.6.0
- Add new mime types
2.0.7 / 2014-12-30
==================
* deps: mime-db@~1.5.0
- Add new mime types
- Fix various invalid MIME type entries
2.0.6 / 2014-12-30
==================
* deps: mime-db@~1.4.0
- Add new mime types
- Fix various invalid MIME type entries
- Remove example template MIME types
2.0.5 / 2014-12-29
==================
* deps: mime-db@~1.3.1
- Fix missing extensions
2.0.4 / 2014-12-10
==================
* deps: mime-db@~1.3.0
- Add new mime types
2.0.3 / 2014-11-09
==================
* deps: mime-db@~1.2.0
- Add new mime types
2.0.2 / 2014-09-28
==================
* deps: mime-db@~1.1.0
- Add new mime types
- Add additional compressible
- Update charsets
2.0.1 / 2014-09-07
==================
* Support Node.js 0.6
2.0.0 / 2014-09-02
==================
* Use `mime-db`
* Remove `.define()`
1.0.2 / 2014-08-04
==================
* Set charset=utf-8 for `text/javascript`
1.0.1 / 2014-06-24
==================
* Add `text/jsx` type
1.0.0 / 2014-05-12
==================
* Return `false` for unknown types
* Set charset=utf-8 for `application/json`
0.1.0 / 2014-05-02
==================
* Initial release
The MIT License (MIT)
Copyright (c) 2014 Jonathan Ong me@jongleberry.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# mime-types
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
The ultimate javascript content-type utility.
Similar to [node-mime](https://github.com/broofa/node-mime), except:
- __No fallbacks.__ Instead of naively returning the first available type, `mime-types` simply returns `false`,
so do `var type = mime.lookup('unrecognized') || 'application/octet-stream'`.
- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.
- Additional mime types are added such as jade and stylus via [mime-db](https://github.com/jshttp/mime-db)
- No `.define()` functionality
Otherwise, the API is compatible.
## Install
```sh
$ npm install mime-types
```
## Adding Types
All mime types are based on [mime-db](https://github.com/jshttp/mime-db),
so open a PR there if you'd like to add mime types.
## API
```js
var mime = require('mime-types')
```
All functions return `false` if input is invalid or not found.
### mime.lookup(path)
Lookup the content-type associated with a file.
```js
mime.lookup('json') // 'application/json'
mime.lookup('.md') // 'text/x-markdown'
mime.lookup('file.html') // 'text/html'
mime.lookup('folder/file.js') // 'application/javascript'
mime.lookup('cats') // false
```
### mime.contentType(type)
Create a full content-type header given a content-type or extension.
```js
mime.contentType('markdown') // 'text/x-markdown; charset=utf-8'
mime.contentType('file.json') // 'application/json; charset=utf-8'
```
### mime.extension(type)
Get the default extension for a content-type.
```js
mime.extension('application/octet-stream') // 'bin'
```
### mime.charset(type)
Lookup the implied default charset of a content-type.
```js
mime.charset('text/x-markdown') // 'UTF-8'
```
### var type = mime.types[extension]
A map of content-types by extension.
### [extensions...] = mime.extensions[type]
A map of extensions by content-type.
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/mime-types.svg?style=flat
[npm-url]: https://npmjs.org/package/mime-types
[node-version-image]: https://img.shields.io/badge/node.js-%3E%3D_0.6-brightgreen.svg?style=flat
[node-version-url]: http://nodejs.org/download/
[travis-image]: https://img.shields.io/travis/jshttp/mime-types.svg?style=flat
[travis-url]: https://travis-ci.org/jshttp/mime-types
[coveralls-image]: https://img.shields.io/coveralls/jshttp/mime-types.svg?style=flat
[coveralls-url]: https://coveralls.io/r/jshttp/mime-types
[downloads-image]: https://img.shields.io/npm/dm/mime-types.svg?style=flat
[downloads-url]: https://npmjs.org/package/mime-types
var db = require('mime-db')
// types[extension] = type
exports.types = Object.create(null)
// extensions[type] = [extensions]
exports.extensions = Object.create(null)
Object.keys(db).forEach(function (name) {
var mime = db[name]
var exts = mime.extensions
if (!exts || !exts.length) return
exports.extensions[name] = exts
exts.forEach(function (ext) {
exports.types[ext] = name
})
})
exports.lookup = function (string) {
if (!string || typeof string !== "string") return false
// remove any leading paths, though we should just use path.basename
string = string.replace(/.*[\.\/\\]/, '').toLowerCase()
if (!string) return false
return exports.types[string] || false
}
exports.extension = function (type) {
if (!type || typeof type !== "string") return false
// to do: use media-typer
type = type.match(/^\s*([^;\s]*)(?:;|\s|$)/)
if (!type) return false
var exts = exports.extensions[type[1].toLowerCase()]
if (!exts || !exts.length) return false
return exts[0]
}
// type has to be an exact mime type
exports.charset = function (type) {
var mime = db[type]
if (mime && mime.charset) return mime.charset
// default text/* to utf-8
if (/^text\//.test(type)) return 'UTF-8'
return false
}
// backwards compatibility
exports.charsets = {
lookup: exports.charset
}
// to do: maybe use set-type module or something
exports.contentType = function (type) {
if (!type || typeof type !== "string") return false
if (!~type.indexOf('/')) type = exports.lookup(type)
if (!type) return false
if (!~type.indexOf('charset')) {
var charset = exports.charset(type)
if (charset) type += '; charset=' + charset.toLowerCase()
}
return type
}
1.7.0 / 2015-02-08
==================
* Add `application/vnd.gerber`
* Add `application/vnd.msa-disk-image`
1.6.1 / 2015-02-05
==================
* Community extensions ownership transferred from `node-mime`
1.6.0 / 2015-01-29
==================
* Add `application/jose`
* Add `application/jose+json`
* Add `application/json-seq`
* Add `application/jwk+json`
* Add `application/jwk-set+json`
* Add `application/jwt`
* Add `application/rdap+json`
* Add `application/vnd.gov.sk.e-form+xml`
* Add `application/vnd.ims.imsccv1p3`
1.5.0 / 2014-12-30
==================
* Add `application/vnd.oracle.resource+json`
* Fix various invalid MIME type entries
- `application/mbox+xml`
- `application/oscp-response`
- `application/vwg-multiplexed`
- `audio/g721`
1.4.0 / 2014-12-21
==================
* Add `application/vnd.ims.imsccv1p2`
* Fix various invalid MIME type entries
- `application/vnd-acucobol`
- `application/vnd-curl`
- `application/vnd-dart`
- `application/vnd-dxr`
- `application/vnd-fdf`
- `application/vnd-mif`
- `application/vnd-sema`
- `application/vnd-wap-wmlc`
- `application/vnd.adobe.flash-movie`
- `application/vnd.dece-zip`
- `application/vnd.dvb_service`
- `application/vnd.micrografx-igx`
- `application/vnd.sealed-doc`
- `application/vnd.sealed-eml`
- `application/vnd.sealed-mht`
- `application/vnd.sealed-ppt`
- `application/vnd.sealed-tiff`
- `application/vnd.sealed-xls`
- `application/vnd.sealedmedia.softseal-html`
- `application/vnd.sealedmedia.softseal-pdf`
- `application/vnd.wap-slc`
- `application/vnd.wap-wbxml`
- `audio/vnd.sealedmedia.softseal-mpeg`
- `image/vnd-djvu`
- `image/vnd-svf`
- `image/vnd-wap-wbmp`
- `image/vnd.sealed-png`
- `image/vnd.sealedmedia.softseal-gif`
- `image/vnd.sealedmedia.softseal-jpg`
- `model/vnd-dwf`
- `model/vnd.parasolid.transmit-binary`
- `model/vnd.parasolid.transmit-text`
- `text/vnd-a`
- `text/vnd-curl`
- `text/vnd.wap-wml`
* Remove example template MIME types
- `application/example`
- `audio/example`
- `image/example`
- `message/example`
- `model/example`
- `multipart/example`
- `text/example`
- `video/example`
1.3.1 / 2014-12-16
==================
* Fix missing extensions
- `application/json5`
- `text/hjson`
1.3.0 / 2014-12-07
==================
* Add `application/a2l`
* Add `application/aml`
* Add `application/atfx`
* Add `application/atxml`
* Add `application/cdfx+xml`
* Add `application/dii`
* Add `application/json5`
* Add `application/lxf`
* Add `application/mf4`
* Add `application/vnd.apache.thrift.compact`
* Add `application/vnd.apache.thrift.json`
* Add `application/vnd.coffeescript`
* Add `application/vnd.enphase.envoy`
* Add `application/vnd.ims.imsccv1p1`
* Add `text/csv-schema`
* Add `text/hjson`
* Add `text/markdown`
* Add `text/yaml`
1.2.0 / 2014-11-09
==================
* Add `application/cea`
* Add `application/dit`
* Add `application/vnd.gov.sk.e-form+zip`
* Add `application/vnd.tmd.mediaflex.api+xml`
* Type `application/epub+zip` is now IANA-registered
1.1.2 / 2014-10-23
==================
* Rebuild database for `application/x-www-form-urlencoded` change
1.1.1 / 2014-10-20
==================
* Mark `application/x-www-form-urlencoded` as compressible.
1.1.0 / 2014-09-28
==================
* Add `application/font-woff2`
1.0.3 / 2014-09-25
==================
* Fix engine requirement in package
1.0.2 / 2014-09-25
==================
* Add `application/coap-group+json`
* Add `application/dcd`
* Add `application/vnd.apache.thrift.binary`
* Add `image/vnd.tencent.tap`
* Mark all JSON-derived types as compressible
* Update `text/vtt` data
1.0.1 / 2014-08-30
==================
* Fix extension ordering
1.0.0 / 2014-08-30
==================
* Add `application/atf`
* Add `application/merge-patch+json`
* Add `multipart/x-mixed-replace`
* Add `source: 'apache'` metadata
* Add `source: 'iana'` metadata
* Remove badly-assumed charset data
The MIT License (MIT)
Copyright (c) 2014 Jonathan Ong me@jongleberry.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# mime-db
[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-image]][node-url]
[![Build Status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]
This is a database of all mime types.
It consists of a single, public JSON file and does not include any logic,
allowing it to remain as un-opinionated as possible with an API.
It aggregates data from the following sources:
- http://www.iana.org/assignments/media-types/media-types.xhtml
- http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
## Installation
```bash
npm install mime-db
```
If you're crazy enough to use this in the browser,
you can just grab the JSON file:
```
https://cdn.rawgit.com/jshttp/mime-db/master/db.json
```
## Usage
```js
var db = require('mime-db');
// grab data on .js files
var data = db['application/javascript'];
```
## Data Structure
The JSON file is a map lookup for lowercased mime types.
Each mime type has the following properties:
- `.source` - where the mime type is defined.
If not set, it's probably a custom media type.
- `apache` - [Apache common media types](http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types)
- `iana` - [IANA-defined media types](http://www.iana.org/assignments/media-types/media-types.xhtml)
- `.extensions[]` - known extensions associated with this mime type.
- `.compressible` - whether a file of this type is can be gzipped.
- `.charset` - the default charset associated with this type, if any.
If unknown, every property could be `undefined`.
## Contributing
To edit the database, only make PRs against `src/custom.json` or
`src/custom-suffix.json`.
To update the build, run `npm run update`.
## Adding Custom Media Types
The best way to get new media types included in this library is to register
them with the IANA. The community registration procedure is outlined in
[RFC 6838 section 5](http://tools.ietf.org/html/rfc6838#section-5). Types
registered with the IANA are automatically pulled into this library.
[npm-version-image]: https://img.shields.io/npm/v/mime-db.svg?style=flat
[npm-downloads-image]: https://img.shields.io/npm/dm/mime-db.svg?style=flat
[npm-url]: https://npmjs.org/package/mime-db
[travis-image]: https://img.shields.io/travis/jshttp/mime-db.svg?style=flat
[travis-url]: https://travis-ci.org/jshttp/mime-db
[coveralls-image]: https://img.shields.io/coveralls/jshttp/mime-db.svg?style=flat
[coveralls-url]: https://coveralls.io/r/jshttp/mime-db?branch=master
[node-image]: https://img.shields.io/node/v/mime-db.svg?style=flat
[node-url]: http://nodejs.org/download/
/*!
* mime-db
* Copyright(c) 2014 Jonathan Ong
* MIT Licensed
*/
/**
* Module exports.
*/
module.exports = require('./db.json')
{
"name": "mime-db",
"description": "Media Type Database",
"version": "1.7.0",
"author": {
"name": "Jonathan Ong",
"email": "me@jongleberry.com",
"url": "http://jongleberry.com"
},
"contributors": [
{
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
{
"name": "Robert Kieffer",
"email": "robert@broofa.com",
"url": "http://github.com/broofa"
}
],
"license": "MIT",
"keywords": [
"mime",
"db",
"type",
"types",
"database",
"charset",
"charsets"
],
"repository": {
"type": "git",
"url": "https://github.com/jshttp/mime-db"
},
"devDependencies": {
"co": "4",
"cogent": "1",
"csv-parse": "0",
"gnode": "0.1.0",
"istanbul": "0.3.5",
"mocha": "~1.21.4",
"raw-body": "~1.3.2",
"stream-to-array": "2"
},
"files": [
"HISTORY.md",
"LICENSE",
"README.md",
"db.json",
"index.js"
],
"engines": {
"node": ">= 0.6"
},
"scripts": {
"build": "node scripts/build",
"fetch": "gnode scripts/extensions && gnode scripts/types",
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
"update": "npm run fetch && npm run build"
},
"gitHead": "972cc3ed48530ab7aca7a155bf2dbd1b13aa8f86",
"bugs": {
"url": "https://github.com/jshttp/mime-db/issues"
},
"homepage": "https://github.com/jshttp/mime-db",
"_id": "mime-db@1.7.0",
"_shasum": "36cf66a6c52ea71827bde287f77c254f5ef1b8d3",
"_from": "mime-db@~1.7.0",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
},
{
"name": "dougwilson",
"email": "doug@somethingdoug.com"
}
],
"dist": {
"shasum": "36cf66a6c52ea71827bde287f77c254f5ef1b8d3",
"tarball": "http://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz",
"readme": "ERROR: No README data found!"
}
{
"name": "mime-types",
"description": "The ultimate javascript content-type utility.",
"version": "2.0.9",
"contributors": [
{
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
{
"name": "Jeremiah Senkpiel",
"email": "fishrock123@rocketmail.com",
"url": "https://searchbeam.jit.su"
},
{
"name": "Jonathan Ong",
"email": "me@jongleberry.com",
"url": "http://jongleberry.com"
}
],
"license": "MIT",
"keywords": [
"mime",
"types"
],
"repository": {
"type": "git",
"url": "https://github.com/jshttp/mime-types"
},
"dependencies": {
"mime-db": "~1.7.0"
},
"devDependencies": {
"istanbul": "0.3.5",
"mocha": "~1.21.5"
},
"files": [
"HISTORY.md",
"LICENSE",
"index.js"
],
"engines": {
"node": ">= 0.6"
},
"scripts": {
"test": "mocha --reporter spec test/test.js",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/test.js",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot test/test.js"
},
"gitHead": "1c6d55da440b6a9d2c0e9c2faac98e6b1be47fc7",
"bugs": {
"url": "https://github.com/jshttp/mime-types/issues"
},
"homepage": "https://github.com/jshttp/mime-types",
"_id": "mime-types@2.0.9",
"_shasum": "e8449aff27b1245ddc6641b524439ae80c4b78a6",
"_from": "mime-types@~2.0.9",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
},
{
"name": "fishrock123",
"email": "fishrock123@rocketmail.com"
},
{
"name": "dougwilson",
"email": "doug@somethingdoug.com"
}
],
"dist": {
"shasum": "e8449aff27b1245ddc6641b524439ae80c4b78a6",
"tarball": "http://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.9.tgz",
"readme": "ERROR: No README data found!"
}
0.5.1 / 2015-02-14
==================
* Fix preference sorting to be stable for long acceptable lists
0.5.0 / 2014-12-18
==================
* Fix list return order when large accepted list
* Fix missing identity encoding when q=0 exists
* Remove dynamic building of Negotiator class
0.4.9 / 2014-10-14
==================
* Fix error when media type has invalid parameter
0.4.8 / 2014-09-28
==================
* Fix all negotiations to be case-insensitive
* Stable sort preferences of same quality according to client order
* Support Node.js 0.6
0.4.7 / 2014-06-24
==================
* Handle invalid provided languages
* Handle invalid provided media types
0.4.6 / 2014-06-11
==================
* Order by specificity when quality is the same
0.4.5 / 2014-05-29
==================
* Fix regression in empty header handling
0.4.4 / 2014-05-29
==================
* Fix behaviors when headers are not present
0.4.3 / 2014-04-16
==================
* Handle slashes on media params correctly
0.4.2 / 2014-02-28
==================
* Fix media type sorting
* Handle media types params strictly
0.4.1 / 2014-01-16
==================
* Use most specific matches
0.4.0 / 2014-01-09
==================
* Remove preferred prefix from methods
(The MIT License)
Copyright (c) 2012 Federico Romero
Copyright (c) 2012-2014 Isaac Z. Schlueter
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# negotiator
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
An HTTP content negotiator for Node.js
## Installation
```sh
$ npm install negotiator
```
## API
```js
var Negotiator = require('negotiator')
```
### Accept Negotiation
```js
availableMediaTypes = ['text/html', 'text/plain', 'application/json']
// The negotiator constructor receives a request object
negotiator = new Negotiator(request)
// Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'
negotiator.mediaTypes()
// -> ['text/html', 'image/jpeg', 'application/*']
negotiator.mediaTypes(availableMediaTypes)
// -> ['text/html', 'application/json']
negotiator.mediaType(availableMediaTypes)
// -> 'text/html'
```
You can check a working example at `examples/accept.js`.
#### Methods
##### mediaType()
Returns the most preferred media type from the client.
##### mediaType(availableMediaType)
Returns the most preferred media type from a list of available media types.
##### mediaTypes()
Returns an array of preferred media types ordered by the client preference.
##### mediaTypes(availableMediaTypes)
Returns an array of preferred media types ordered by priority from a list of
available media types.
### Accept-Language Negotiation
```js
negotiator = new Negotiator(request)
availableLanguages = 'en', 'es', 'fr'
// Let's say Accept-Language header is 'en;q=0.8, es, pt'
negotiator.languages()
// -> ['es', 'pt', 'en']
negotiator.languages(availableLanguages)
// -> ['es', 'en']
language = negotiator.language(availableLanguages)
// -> 'es'
```
You can check a working example at `examples/language.js`.
#### Methods
##### language()
Returns the most preferred language from the client.
##### language(availableLanguages)
Returns the most preferred language from a list of available languages.
##### languages()
Returns an array of preferred languages ordered by the client preference.
##### languages(availableLanguages)
Returns an array of preferred languages ordered by priority from a list of
available languages.
### Accept-Charset Negotiation
```js
availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']
negotiator = new Negotiator(request)
// Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'
negotiator.charsets()
// -> ['utf-8', 'iso-8859-1', 'utf-7']
negotiator.charsets(availableCharsets)
// -> ['utf-8', 'iso-8859-1']
negotiator.charset(availableCharsets)
// -> 'utf-8'
```
You can check a working example at `examples/charset.js`.
#### Methods
##### charset()
Returns the most preferred charset from the client.
##### charset(availableCharsets)
Returns the most preferred charset from a list of available charsets.
##### charsets()
Returns an array of preferred charsets ordered by the client preference.
##### charsets(availableCharsets)
Returns an array of preferred charsets ordered by priority from a list of
available charsets.
### Accept-Encoding Negotiation
```js
availableEncodings = ['identity', 'gzip']
negotiator = new Negotiator(request)
// Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'
negotiator.encodings()
// -> ['gzip', 'identity', 'compress']
negotiator.encodings(availableEncodings)
// -> ['gzip', 'identity']
negotiator.encoding(availableEncodings)
// -> 'gzip'
```
You can check a working example at `examples/encoding.js`.
#### Methods
##### encoding()
Returns the most preferred encoding from the client.
##### encoding(availableEncodings)
Returns the most preferred encoding from a list of available encodings.
##### encodings()
Returns an array of preferred encodings ordered by the client preference.
##### encodings(availableEncodings)
Returns an array of preferred encodings ordered by priority from a list of
available encodings.
## See Also
The [accepts](https://npmjs.org/package/accepts#readme) module builds on
this module and provides an alternative interface, mime type validation,
and more.
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/negotiator.svg
[npm-url]: https://npmjs.org/package/negotiator
[node-version-image]: https://img.shields.io/node/v/negotiator.svg
[node-version-url]: http://nodejs.org/download/
[travis-image]: https://img.shields.io/travis/jshttp/negotiator/master.svg
[travis-url]: https://travis-ci.org/jshttp/negotiator
[coveralls-image]: https://img.shields.io/coveralls/jshttp/negotiator/master.svg
[coveralls-url]: https://coveralls.io/r/jshttp/negotiator?branch=master
[downloads-image]: https://img.shields.io/npm/dm/negotiator.svg
[downloads-url]: https://npmjs.org/package/negotiator
var preferredCharsets = require('./lib/charset');
var preferredEncodings = require('./lib/encoding');
var preferredLanguages = require('./lib/language');
var preferredMediaTypes = require('./lib/mediaType');
module.exports = Negotiator;
Negotiator.Negotiator = Negotiator;
function Negotiator(request) {
if (!(this instanceof Negotiator)) {
return new Negotiator(request);
}
this.request = request;
}
Negotiator.prototype.charset = function charset(available) {
var set = this.charsets(available);
return set && set[0];
};
Negotiator.prototype.charsets = function charsets(available) {
return preferredCharsets(this.request.headers['accept-charset'], available);
};
Negotiator.prototype.encoding = function encoding(available) {
var set = this.encodings(available);
return set && set[0];
};
Negotiator.prototype.encodings = function encodings(available) {
return preferredEncodings(this.request.headers['accept-encoding'], available);
};
Negotiator.prototype.language = function language(available) {
var set = this.languages(available);
return set && set[0];
};
Negotiator.prototype.languages = function languages(available) {
return preferredLanguages(this.request.headers['accept-language'], available);
};
Negotiator.prototype.mediaType = function mediaType(available) {
var set = this.mediaTypes(available);
return set && set[0];
};
Negotiator.prototype.mediaTypes = function mediaTypes(available) {
return preferredMediaTypes(this.request.headers.accept, available);
};
// Backwards compatibility
Negotiator.prototype.preferredCharset = Negotiator.prototype.charset;
Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets;
Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding;
Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings;
Negotiator.prototype.preferredLanguage = Negotiator.prototype.language;
Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages;
Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType;
Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes;
module.exports = preferredCharsets;
preferredCharsets.preferredCharsets = preferredCharsets;
function parseAcceptCharset(accept) {
var accepts = accept.split(',');
for (var i = 0, j = 0; i < accepts.length; i++) {
var charset = parseCharset(accepts[i].trim(), i);
if (charset) {
accepts[j++] = charset;
}
}
// trim accepts
accepts.length = j;
return accepts;
}
function parseCharset(s, i) {
var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
if (!match) return null;
var charset = match[1];
var q = 1;
if (match[2]) {
var params = match[2].split(';')
for (var i = 0; i < params.length; i ++) {
var p = params[i].trim().split('=');
if (p[0] === 'q') {
q = parseFloat(p[1]);
break;
}
}
}
return {
charset: charset,
q: q,
i: i
};
}
function getCharsetPriority(charset, accepted, index) {
var priority = {o: -1, q: 0, s: 0};
for (var i = 0; i < accepted.length; i++) {
var spec = specify(charset, accepted[i], index);
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
priority = spec;
}
}
return priority;
}
function specify(charset, spec, index) {
var s = 0;
if(spec.charset.toLowerCase() === charset.toLowerCase()){
s |= 1;
} else if (spec.charset !== '*' ) {
return null
}
return {
i: index,
o: spec.i,
q: spec.q,
s: s
}
}
function preferredCharsets(accept, provided) {
// RFC 2616 sec 14.2: no header = *
var accepts = parseAcceptCharset(accept === undefined ? '*' : accept || '');
if (!provided) {
// sorted list of all charsets
return accepts.filter(isQuality).sort(compareSpecs).map(function getCharset(spec) {
return spec.charset;
});
}
var priorities = provided.map(function getPriority(type, index) {
return getCharsetPriority(type, accepts, index);
});
// sorted list of accepted charsets
return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) {
return provided[priorities.indexOf(priority)];
});
}
function compareSpecs(a, b) {
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
}
function isQuality(spec) {
return spec.q > 0;
}
module.exports = preferredEncodings;
preferredEncodings.preferredEncodings = preferredEncodings;
function parseAcceptEncoding(accept) {
var accepts = accept.split(',');
var hasIdentity = false;
var minQuality = 1;
for (var i = 0, j = 0; i < accepts.length; i++) {
var encoding = parseEncoding(accepts[i].trim(), i);
if (encoding) {
accepts[j++] = encoding;
hasIdentity = hasIdentity || specify('identity', encoding);
minQuality = Math.min(minQuality, encoding.q || 1);
}
}
if (!hasIdentity) {
/*
* If identity doesn't explicitly appear in the accept-encoding header,
* it's added to the list of acceptable encoding with the lowest q
*/
accepts[j++] = {
encoding: 'identity',
q: minQuality,
i: i
};
}
// trim accepts
accepts.length = j;
return accepts;
}
function parseEncoding(s, i) {
var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
if (!match) return null;
var encoding = match[1];
var q = 1;
if (match[2]) {
var params = match[2].split(';');
for (var i = 0; i < params.length; i ++) {
var p = params[i].trim().split('=');
if (p[0] === 'q') {
q = parseFloat(p[1]);
break;
}
}
}
return {
encoding: encoding,
q: q,
i: i
};
}
function getEncodingPriority(encoding, accepted, index) {
var priority = {o: -1, q: 0, s: 0};
for (var i = 0; i < accepted.length; i++) {
var spec = specify(encoding, accepted[i], index);
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
priority = spec;
}
}
return priority;
}
function specify(encoding, spec, index) {
var s = 0;
if(spec.encoding.toLowerCase() === encoding.toLowerCase()){
s |= 1;
} else if (spec.encoding !== '*' ) {
return null
}
return {
i: index,
o: spec.i,
q: spec.q,
s: s
}
};
function preferredEncodings(accept, provided) {
var accepts = parseAcceptEncoding(accept || '');
if (!provided) {
// sorted list of all encodings
return accepts.filter(isQuality).sort(compareSpecs).map(function getEncoding(spec) {
return spec.encoding;
});
}
var priorities = provided.map(function getPriority(type, index) {
return getEncodingPriority(type, accepts, index);
});
// sorted list of accepted encodings
return priorities.filter(isQuality).sort(compareSpecs).map(function getEncoding(priority) {
return provided[priorities.indexOf(priority)];
});
}
function compareSpecs(a, b) {
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
}
function isQuality(spec) {
return spec.q > 0;
}
module.exports = preferredLanguages;
preferredLanguages.preferredLanguages = preferredLanguages;
function parseAcceptLanguage(accept) {
var accepts = accept.split(',');
for (var i = 0, j = 0; i < accepts.length; i++) {
var langauge = parseLanguage(accepts[i].trim(), i);
if (langauge) {
accepts[j++] = langauge;
}
}
// trim accepts
accepts.length = j;
return accepts;
}
function parseLanguage(s, i) {
var match = s.match(/^\s*(\S+?)(?:-(\S+?))?\s*(?:;(.*))?$/);
if (!match) return null;
var prefix = match[1],
suffix = match[2],
full = prefix;
if (suffix) full += "-" + suffix;
var q = 1;
if (match[3]) {
var params = match[3].split(';')
for (var i = 0; i < params.length; i ++) {
var p = params[i].split('=');
if (p[0] === 'q') q = parseFloat(p[1]);
}
}
return {
prefix: prefix,
suffix: suffix,
q: q,
i: i,
full: full
};
}
function getLanguagePriority(language, accepted, index) {
var priority = {o: -1, q: 0, s: 0};
for (var i = 0; i < accepted.length; i++) {
var spec = specify(language, accepted[i], index);
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
priority = spec;
}
}
return priority;
}
function specify(language, spec, index) {
var p = parseLanguage(language)
if (!p) return null;
var s = 0;
if(spec.full.toLowerCase() === p.full.toLowerCase()){
s |= 4;
} else if (spec.prefix.toLowerCase() === p.full.toLowerCase()) {
s |= 2;
} else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {
s |= 1;
} else if (spec.full !== '*' ) {
return null
}
return {
i: index,
o: spec.i,
q: spec.q,
s: s
}
};
function preferredLanguages(accept, provided) {
// RFC 2616 sec 14.4: no header = *
var accepts = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
if (!provided) {
// sorted list of all languages
return accepts.filter(isQuality).sort(compareSpecs).map(function getLanguage(spec) {
return spec.full;
});
}
var priorities = provided.map(function getPriority(type, index) {
return getLanguagePriority(type, accepts, index);
});
// sorted list of accepted languages
return priorities.filter(isQuality).sort(compareSpecs).map(function getLanguage(priority) {
return provided[priorities.indexOf(priority)];
});
}
function compareSpecs(a, b) {
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
}
function isQuality(spec) {
return spec.q > 0;
}
module.exports = preferredMediaTypes;
preferredMediaTypes.preferredMediaTypes = preferredMediaTypes;
function parseAccept(accept) {
var accepts = accept.split(',');
for (var i = 0, j = 0; i < accepts.length; i++) {
var mediaType = parseMediaType(accepts[i].trim(), i);
if (mediaType) {
accepts[j++] = mediaType;
}
}
// trim accepts
accepts.length = j;
return accepts;
};
function parseMediaType(s, i) {
var match = s.match(/\s*(\S+?)\/([^;\s]+)\s*(?:;(.*))?/);
if (!match) return null;
var type = match[1],
subtype = match[2],
full = "" + type + "/" + subtype,
params = {},
q = 1;
if (match[3]) {
params = match[3].split(';').map(function(s) {
return s.trim().split('=');
}).reduce(function (set, p) {
set[p[0]] = p[1];
return set
}, params);
if (params.q != null) {
q = parseFloat(params.q);
delete params.q;
}
}
return {
type: type,
subtype: subtype,
params: params,
q: q,
i: i,
full: full
};
}
function getMediaTypePriority(type, accepted, index) {
var priority = {o: -1, q: 0, s: 0};
for (var i = 0; i < accepted.length; i++) {
var spec = specify(type, accepted[i], index);
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
priority = spec;
}
}
return priority;
}
function specify(type, spec, index) {
var p = parseMediaType(type);
var s = 0;
if (!p) {
return null;
}
if(spec.type.toLowerCase() == p.type.toLowerCase()) {
s |= 4
} else if(spec.type != '*') {
return null;
}
if(spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
s |= 2
} else if(spec.subtype != '*') {
return null;
}
var keys = Object.keys(spec.params);
if (keys.length > 0) {
if (keys.every(function (k) {
return spec.params[k] == '*' || (spec.params[k] || '').toLowerCase() == (p.params[k] || '').toLowerCase();
})) {
s |= 1
} else {
return null
}
}
return {
i: index,
o: spec.i,
q: spec.q,
s: s,
}
}
function preferredMediaTypes(accept, provided) {
// RFC 2616 sec 14.2: no header = */*
var accepts = parseAccept(accept === undefined ? '*/*' : accept || '');
if (!provided) {
// sorted list of all types
return accepts.filter(isQuality).sort(compareSpecs).map(function getType(spec) {
return spec.full;
});
}
var priorities = provided.map(function getPriority(type, index) {
return getMediaTypePriority(type, accepts, index);
});
// sorted list of accepted types
return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
return provided[priorities.indexOf(priority)];
});
}
function compareSpecs(a, b) {
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
}
function isQuality(spec) {
return spec.q > 0;
}
{
"name": "negotiator",
"description": "HTTP content negotiation",
"version": "0.5.1",
"contributors": [
{
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
{
"name": "Federico Romero",
"email": "federico.romero@outboxlabs.com"
},
{
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
}
],
"license": "MIT",
"keywords": [
"http",
"content negotiation",
"accept",
"accept-language",
"accept-encoding",
"accept-charset"
],
"repository": {
"type": "git",
"url": "https://github.com/jshttp/negotiator"
},
"devDependencies": {
"istanbul": "0.3.5",
"nodeunit": "0.9.0",
"tap": "0.5.0"
},
"files": [
"lib/",
"HISTORY.md",
"LICENSE",
"index.js",
"README.md"
],
"engines": {
"node": ">= 0.6"
},
"scripts": {
"test": "nodeunit test",
"test-cov": "istanbul cover ./node_modules/nodeunit/bin/nodeunit test"
},
"gitHead": "bfee971fe0503518cc93d1956518212203b7e68c",
"bugs": {
"url": "https://github.com/jshttp/negotiator/issues"
},
"homepage": "https://github.com/jshttp/negotiator",
"_id": "negotiator@0.5.1",
"_shasum": "498f661c522470153c6086ac83019cb3eb66f61c",
"_from": "negotiator@0.5.1",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "federomero",
"email": "federomero@gmail.com"
},
{
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
}
],
"dist": {
"shasum": "498f661c522470153c6086ac83019cb3eb66f61c",
"tarball": "http://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz",
"readme": "ERROR: No README data found!"
}
{
"name": "accepts",
"description": "Higher-level content negotiation",
"version": "1.2.4",
"author": {
"name": "Jonathan Ong",
"email": "me@jongleberry.com",
"url": "http://jongleberry.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/jshttp/accepts"
},
"dependencies": {
"mime-types": "~2.0.9",
"negotiator": "0.5.1"
},
"devDependencies": {
"istanbul": "0.3.5",
"mocha": "~1.21.5"
},
"files": [
"LICENSE",
"HISTORY.md",
"index.js"
],
"engines": {
"node": ">= 0.6"
},
"scripts": {
"test": "mocha --reporter spec --check-leaks --bail test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
},
"keywords": [
"content",
"negotiation",
"accept",
"accepts"
],
"gitHead": "dfa143a31879bf5fb4934bbefc5741504a1cc15f",
"bugs": {
"url": "https://github.com/jshttp/accepts/issues"
},
"homepage": "https://github.com/jshttp/accepts",
"_id": "accepts@1.2.4",
"_shasum": "f4e6c66f4faf69c76bd7a63a1ffc5bd2dacfb2ac",
"_from": "accepts@~1.2.4",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
},
{
"name": "federomero",
"email": "federomero@gmail.com"
},
{
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
{
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
},
{
"name": "shtylman",
"email": "shtylman@gmail.com"
},
{
"name": "mscdex",
"email": "mscdex@mscdex.net"
},
{
"name": "fishrock123",
"email": "fishrock123@rocketmail.com"
}
],
"dist": {
"shasum": "f4e6c66f4faf69c76bd7a63a1ffc5bd2dacfb2ac",
"tarball": "http://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz",
"readme": "ERROR: No README data found!"
}
1.0.0 / 2014-05-05
==================
* add negative support. fixes #6
0.3.0 / 2014-03-19
==================
* added terabyte support
0.2.1 / 2013-04-01
==================
* add .component
0.2.0 / 2012-10-28
==================
* bytes(200).should.eql('200b')
0.1.0 / 2012-07-04
==================
* add bytes to string conversion [yields]
test:
@./node_modules/.bin/mocha \
--reporter spec \
--require should
.PHONY: test
\ No newline at end of file
# node-bytes
Byte string parser / formatter.
## Example:
```js
bytes('1kb')
// => 1024
bytes('2mb')
// => 2097152
bytes('1gb')
// => 1073741824
bytes(1073741824)
// => 1gb
bytes(1099511627776)
// => 1tb
```
## Installation
```
$ npm install bytes
$ component install visionmedia/bytes.js
```
## License
(The MIT License)
Copyright (c) 2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
"name": "bytes",
"description": "byte size string parser / serializer",
"keywords": ["bytes", "utility"],
"version": "0.2.1",
"scripts": ["index.js"]
}
/**
* Parse byte `size` string.
*
* @param {String} size
* @return {Number}
* @api public
*/
module.exports = function(size) {
if ('number' == typeof size) return convert(size);
var parts = size.match(/^(\d+(?:\.\d+)?) *(kb|mb|gb|tb)$/)
, n = parseFloat(parts[1])
, type = parts[2];
var map = {
kb: 1 << 10
, mb: 1 << 20
, gb: 1 << 30
, tb: ((1 << 30) * 1024)
};
return map[type] * n;
};
/**
* convert bytes into string.
*
* @param {Number} b - bytes to convert
* @return {String}
* @api public
*/
function convert (b) {
var tb = ((1 << 30) * 1024), gb = 1 << 30, mb = 1 << 20, kb = 1 << 10, abs = Math.abs(b);
if (abs >= tb) return (Math.round(b / tb * 100) / 100) + 'tb';
if (abs >= gb) return (Math.round(b / gb * 100) / 100) + 'gb';
if (abs >= mb) return (Math.round(b / mb * 100) / 100) + 'mb';
if (abs >= kb) return (Math.round(b / kb * 100) / 100) + 'kb';
return b + 'b';
}
{
"name": "bytes",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca",
"url": "http://tjholowaychuk.com"
},
"description": "byte size string parser / serializer",
"repository": {
"type": "git",
"url": "https://github.com/visionmedia/bytes.js.git"
},
"version": "1.0.0",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"mocha": "*",
"should": "*"
},
"component": {
"scripts": {
"bytes/index.js": "index.js"
}
},
"bugs": {
"url": "https://github.com/visionmedia/bytes.js/issues"
},
"homepage": "https://github.com/visionmedia/bytes.js",
"_id": "bytes@1.0.0",
"dist": {
"shasum": "3569ede8ba34315fab99c3e92cb04c7220de1fa8",
"tarball": "http://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz"
},
"_from": "bytes@1.0.0",
"_npmVersion": "1.4.3",
"_npmUser": {
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
},
"maintainers": [
{
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
}
],
"directories": {},
"_shasum": "3569ede8ba34315fab99c3e92cb04c7220de1fa8",
"_resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz",
"readme": "ERROR: No README data found!"
}
The MIT License (MIT)
Copyright (c) 2013 Jonathan Ong me@jongleberry.com
Copyright (c) 2014 Jeremiah Senkpiel fishrock123@rocketmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# compressible
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
Compressible `Content-Type` / `mime` checking.
### Installation
```bash
$ npm install compressible
```
## API
### compressible(type)
Checks if the given content-type is compressible.
```js
var compressible = require('compressible')
compressible('text/html') // => true
compressible('image/png') // => false
```
## [MIT Licensed](LICENSE)
[npm-image]: https://img.shields.io/npm/v/compressible.svg?style=flat
[npm-url]: https://npmjs.org/package/compressible
[node-version-image]: https://img.shields.io/badge/node.js-%3E%3D_0.6-brightgreen.svg?style=flat
[node-version-url]: http://nodejs.org/download/
[travis-image]: https://img.shields.io/travis/jshttp/compressible.svg?style=flat
[travis-url]: https://travis-ci.org/jshttp/compressible
[coveralls-image]: https://img.shields.io/coveralls/jshttp/compressible.svg?style=flat
[coveralls-url]: https://coveralls.io/r/jshttp/compressible?branch=master
[downloads-image]: https://img.shields.io/npm/dm/compressible.svg?style=flat
[downloads-url]: https://npmjs.org/package/compressible
/*!
* compressible
* Copyright(c) 2014 Jeremiah Senkpiel
* MIT Licensed
*/
/**
* Module dependencies.
*/
var db = require('mime-db')
/**
* Module exports.
*/
module.exports = compressible
/**
* Checks if a type is compressible.
*
* @param {string} type
* @return {Boolean} compressible
*/
function compressible(type) {
if (!type || typeof type !== "string") return false
// Strip charset
var i = type.indexOf(';')
if (~i) type = type.slice(0, i)
// handle types that have capitals or excess space
type = type.trim().toLowerCase()
// attempt to look up from database; fallback to regex if not found
var mime = db[type]
return mime ? mime.compressible : /^text\/|\+json$|\+text$|\+xml$/.test(type)
}
1.7.0 / 2015-02-08
==================
* Add `application/vnd.gerber`
* Add `application/vnd.msa-disk-image`
1.6.1 / 2015-02-05
==================
* Community extensions ownership transferred from `node-mime`
1.6.0 / 2015-01-29
==================
* Add `application/jose`
* Add `application/jose+json`
* Add `application/json-seq`
* Add `application/jwk+json`
* Add `application/jwk-set+json`
* Add `application/jwt`
* Add `application/rdap+json`
* Add `application/vnd.gov.sk.e-form+xml`
* Add `application/vnd.ims.imsccv1p3`
1.5.0 / 2014-12-30
==================
* Add `application/vnd.oracle.resource+json`
* Fix various invalid MIME type entries
- `application/mbox+xml`
- `application/oscp-response`
- `application/vwg-multiplexed`
- `audio/g721`
1.4.0 / 2014-12-21
==================
* Add `application/vnd.ims.imsccv1p2`
* Fix various invalid MIME type entries
- `application/vnd-acucobol`
- `application/vnd-curl`
- `application/vnd-dart`
- `application/vnd-dxr`
- `application/vnd-fdf`
- `application/vnd-mif`
- `application/vnd-sema`
- `application/vnd-wap-wmlc`
- `application/vnd.adobe.flash-movie`
- `application/vnd.dece-zip`
- `application/vnd.dvb_service`
- `application/vnd.micrografx-igx`
- `application/vnd.sealed-doc`
- `application/vnd.sealed-eml`
- `application/vnd.sealed-mht`
- `application/vnd.sealed-ppt`
- `application/vnd.sealed-tiff`
- `application/vnd.sealed-xls`
- `application/vnd.sealedmedia.softseal-html`
- `application/vnd.sealedmedia.softseal-pdf`
- `application/vnd.wap-slc`
- `application/vnd.wap-wbxml`
- `audio/vnd.sealedmedia.softseal-mpeg`
- `image/vnd-djvu`
- `image/vnd-svf`
- `image/vnd-wap-wbmp`
- `image/vnd.sealed-png`
- `image/vnd.sealedmedia.softseal-gif`
- `image/vnd.sealedmedia.softseal-jpg`
- `model/vnd-dwf`
- `model/vnd.parasolid.transmit-binary`
- `model/vnd.parasolid.transmit-text`
- `text/vnd-a`
- `text/vnd-curl`
- `text/vnd.wap-wml`
* Remove example template MIME types
- `application/example`
- `audio/example`
- `image/example`
- `message/example`
- `model/example`
- `multipart/example`
- `text/example`
- `video/example`
1.3.1 / 2014-12-16
==================
* Fix missing extensions
- `application/json5`
- `text/hjson`
1.3.0 / 2014-12-07
==================
* Add `application/a2l`
* Add `application/aml`
* Add `application/atfx`
* Add `application/atxml`
* Add `application/cdfx+xml`
* Add `application/dii`
* Add `application/json5`
* Add `application/lxf`
* Add `application/mf4`
* Add `application/vnd.apache.thrift.compact`
* Add `application/vnd.apache.thrift.json`
* Add `application/vnd.coffeescript`
* Add `application/vnd.enphase.envoy`
* Add `application/vnd.ims.imsccv1p1`
* Add `text/csv-schema`
* Add `text/hjson`
* Add `text/markdown`
* Add `text/yaml`
1.2.0 / 2014-11-09
==================
* Add `application/cea`
* Add `application/dit`
* Add `application/vnd.gov.sk.e-form+zip`
* Add `application/vnd.tmd.mediaflex.api+xml`
* Type `application/epub+zip` is now IANA-registered
1.1.2 / 2014-10-23
==================
* Rebuild database for `application/x-www-form-urlencoded` change
1.1.1 / 2014-10-20
==================
* Mark `application/x-www-form-urlencoded` as compressible.
1.1.0 / 2014-09-28
==================
* Add `application/font-woff2`
1.0.3 / 2014-09-25
==================
* Fix engine requirement in package
1.0.2 / 2014-09-25
==================
* Add `application/coap-group+json`
* Add `application/dcd`
* Add `application/vnd.apache.thrift.binary`
* Add `image/vnd.tencent.tap`
* Mark all JSON-derived types as compressible
* Update `text/vtt` data
1.0.1 / 2014-08-30
==================
* Fix extension ordering
1.0.0 / 2014-08-30
==================
* Add `application/atf`
* Add `application/merge-patch+json`
* Add `multipart/x-mixed-replace`
* Add `source: 'apache'` metadata
* Add `source: 'iana'` metadata
* Remove badly-assumed charset data
The MIT License (MIT)
Copyright (c) 2014 Jonathan Ong me@jongleberry.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# mime-db
[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-image]][node-url]
[![Build Status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]
This is a database of all mime types.
It consists of a single, public JSON file and does not include any logic,
allowing it to remain as un-opinionated as possible with an API.
It aggregates data from the following sources:
- http://www.iana.org/assignments/media-types/media-types.xhtml
- http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
## Installation
```bash
npm install mime-db
```
If you're crazy enough to use this in the browser,
you can just grab the JSON file:
```
https://cdn.rawgit.com/jshttp/mime-db/master/db.json
```
## Usage
```js
var db = require('mime-db');
// grab data on .js files
var data = db['application/javascript'];
```
## Data Structure
The JSON file is a map lookup for lowercased mime types.
Each mime type has the following properties:
- `.source` - where the mime type is defined.
If not set, it's probably a custom media type.
- `apache` - [Apache common media types](http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types)
- `iana` - [IANA-defined media types](http://www.iana.org/assignments/media-types/media-types.xhtml)
- `.extensions[]` - known extensions associated with this mime type.
- `.compressible` - whether a file of this type is can be gzipped.
- `.charset` - the default charset associated with this type, if any.
If unknown, every property could be `undefined`.
## Contributing
To edit the database, only make PRs against `src/custom.json` or
`src/custom-suffix.json`.
To update the build, run `npm run update`.
## Adding Custom Media Types
The best way to get new media types included in this library is to register
them with the IANA. The community registration procedure is outlined in
[RFC 6838 section 5](http://tools.ietf.org/html/rfc6838#section-5). Types
registered with the IANA are automatically pulled into this library.
[npm-version-image]: https://img.shields.io/npm/v/mime-db.svg?style=flat
[npm-downloads-image]: https://img.shields.io/npm/dm/mime-db.svg?style=flat
[npm-url]: https://npmjs.org/package/mime-db
[travis-image]: https://img.shields.io/travis/jshttp/mime-db.svg?style=flat
[travis-url]: https://travis-ci.org/jshttp/mime-db
[coveralls-image]: https://img.shields.io/coveralls/jshttp/mime-db.svg?style=flat
[coveralls-url]: https://coveralls.io/r/jshttp/mime-db?branch=master
[node-image]: https://img.shields.io/node/v/mime-db.svg?style=flat
[node-url]: http://nodejs.org/download/
/*!
* mime-db
* Copyright(c) 2014 Jonathan Ong
* MIT Licensed
*/
/**
* Module exports.
*/
module.exports = require('./db.json')
{
"name": "mime-db",
"description": "Media Type Database",
"version": "1.7.0",
"author": {
"name": "Jonathan Ong",
"email": "me@jongleberry.com",
"url": "http://jongleberry.com"
},
"contributors": [
{
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
{
"name": "Robert Kieffer",
"email": "robert@broofa.com",
"url": "http://github.com/broofa"
}
],
"license": "MIT",
"keywords": [
"mime",
"db",
"type",
"types",
"database",
"charset",
"charsets"
],
"repository": {
"type": "git",
"url": "https://github.com/jshttp/mime-db"
},
"devDependencies": {
"co": "4",
"cogent": "1",
"csv-parse": "0",
"gnode": "0.1.0",
"istanbul": "0.3.5",
"mocha": "~1.21.4",
"raw-body": "~1.3.2",
"stream-to-array": "2"
},
"files": [
"HISTORY.md",
"LICENSE",
"README.md",
"db.json",
"index.js"
],
"engines": {
"node": ">= 0.6"
},
"scripts": {
"build": "node scripts/build",
"fetch": "gnode scripts/extensions && gnode scripts/types",
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
"update": "npm run fetch && npm run build"
},
"gitHead": "972cc3ed48530ab7aca7a155bf2dbd1b13aa8f86",
"bugs": {
"url": "https://github.com/jshttp/mime-db/issues"
},
"homepage": "https://github.com/jshttp/mime-db",
"_id": "mime-db@1.7.0",
"_shasum": "36cf66a6c52ea71827bde287f77c254f5ef1b8d3",
"_from": "mime-db@>= 1.1.2 < 2",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
},
{
"name": "dougwilson",
"email": "doug@somethingdoug.com"
}
],
"dist": {
"shasum": "36cf66a6c52ea71827bde287f77c254f5ef1b8d3",
"tarball": "http://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.7.0.tgz",
"readme": "ERROR: No README data found!"
}
{
"name": "compressible",
"description": "Compressible Content-Type / mime checking",
"version": "2.0.2",
"contributors": [
{
"name": "Jonathan Ong",
"email": "me@jongleberry.com",
"url": "http://jongleberry.com"
},
{
"name": "Jeremiah Senkpiel",
"email": "fishrock123@rocketmail.com",
"url": "https://searchbeam.jit.su"
}
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/jshttp/compressible"
},
"keywords": [
"compress",
"gzip",
"mime",
"content-type"
],
"dependencies": {
"mime-db": ">= 1.1.2 < 2"
},
"devDependencies": {
"istanbul": "0.3.5",
"mocha": "~1.21.5"
},
"engines": {
"node": ">= 0.6.0"
},
"files": [
"LICENSE",
"index.js"
],
"scripts": {
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot -check-leaks",
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot --check-leaks"
},
"gitHead": "06e9d6810e86e70dfc17c9805eeecf8b2fa995b5",
"bugs": {
"url": "https://github.com/jshttp/compressible/issues"
},
"homepage": "https://github.com/jshttp/compressible",
"_id": "compressible@2.0.2",
"_shasum": "d0474a6ba6590a43d39c2ce9a6cfbb6479be76a5",
"_from": "compressible@~2.0.2",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
"maintainers": [
{
"name": "jongleberry",
"email": "jonathanrichardong@gmail.com"
},
{
"name": "fishrock123",
"email": "fishrock123@rocketmail.com"
},
{
"name": "federomero",
"email": "federomero@gmail.com"
},
{
"name": "dougwilson",
"email": "doug@somethingdoug.com"
},
{
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
},
{
"name": "shtylman",
"email": "shtylman@gmail.com"
},
{
"name": "mscdex",
"email": "mscdex@mscdex.net"
}
],
"dist": {
"shasum": "d0474a6ba6590a43d39c2ce9a6cfbb6479be76a5",
"tarball": "http://registry.npmjs.org/compressible/-/compressible-2.0.2.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.2.tgz",
"readme": "ERROR: No README data found!"
}
2.1.1 / 2014-12-29
==================
* browser: use `typeof` to check for `console` existence
* browser: check for `console.log` truthiness (fix IE 8/9)
* browser: add support for Chrome apps
* Readme: added Windows usage remarks
* Add `bower.json` to properly support bower install
2.1.0 / 2014-10-15
==================
* node: implement `DEBUG_FD` env variable support
* package: update "browserify" to v6.1.0
* package: add "license" field to package.json (#135, @panuhorsmalahti)
2.0.0 / 2014-09-01
==================
* package: update "browserify" to v5.11.0
* node: use stderr rather than stdout for logging (#29, @stephenmathieson)
1.0.4 / 2014-07-15
==================
* dist: recompile
* example: remove `console.info()` log usage
* example: add "Content-Type" UTF-8 header to browser example
* browser: place %c marker after the space character
* browser: reset the "content" color via `color: inherit`
* browser: add colors support for Firefox >= v31
* debug: prefer an instance `log()` function over the global one (#119)
* Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
1.0.3 / 2014-07-09
==================
* Add support for multiple wildcards in namespaces (#122, @seegno)
* browser: fix lint
1.0.2 / 2014-06-10
==================
* browser: update color palette (#113, @gscottolson)
* common: make console logging function configurable (#108, @timoxley)
* node: fix %o colors on old node <= 0.8.x
* Makefile: find node path using shell/which (#109, @timoxley)
1.0.1 / 2014-06-06
==================
* browser: use `removeItem()` to clear localStorage
* browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
* package: add "contributors" section
* node: fix comment typo
* README: list authors
1.0.0 / 2014-06-04
==================
* make ms diff be global, not be scope
* debug: ignore empty strings in enable()
* node: make DEBUG_COLORS able to disable coloring
* *: export the `colors` array
* npmignore: don't publish the `dist` dir
* Makefile: refactor to use browserify
* package: add "browserify" as a dev dependency
* Readme: add Web Inspector Colors section
* node: reset terminal color for the debug content
* node: map "%o" to `util.inspect()`
* browser: map "%j" to `JSON.stringify()`
* debug: add custom "formatters"
* debug: use "ms" module for humanizing the diff
* Readme: add "bash" syntax highlighting
* browser: add Firebug color support
* browser: add colors for WebKit browsers
* node: apply log to `console`
* rewrite: abstract common logic for Node & browsers
* add .jshintrc file
0.8.1 / 2014-04-14
==================
* package: re-add the "component" section
0.8.0 / 2014-03-30
==================
* add `enable()` method for nodejs. Closes #27
* change from stderr to stdout
* remove unnecessary index.js file
0.7.4 / 2013-11-13
==================
* remove "browserify" key from package.json (fixes something in browserify)
0.7.3 / 2013-10-30
==================
* fix: catch localStorage security error when cookies are blocked (Chrome)
* add debug(err) support. Closes #46
* add .browser prop to package.json. Closes #42
0.7.2 / 2013-02-06
==================
* fix package.json
* fix: Mobile Safari (private mode) is broken with debug
* fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
0.7.1 / 2013-02-05
==================
* add repository URL to package.json
* add DEBUG_COLORED to force colored output
* add browserify support
* fix component. Closes #24
0.7.0 / 2012-05-04
==================
* Added .component to package.json
* Added debug.component.js build
0.6.0 / 2012-03-16
==================
* Added support for "-" prefix in DEBUG [Vinay Pulim]
* Added `.enabled` flag to the node version [TooTallNate]
0.5.0 / 2012-02-02
==================
* Added: humanize diffs. Closes #8
* Added `debug.disable()` to the CS variant
* Removed padding. Closes #10
* Fixed: persist client-side variant again. Closes #9
0.4.0 / 2012-02-01
==================
* Added browser variant support for older browsers [TooTallNate]
* Added `debug.enable('project:*')` to browser variant [TooTallNate]
* Added padding to diff (moved it to the right)
0.3.0 / 2012-01-26
==================
* Added millisecond diff when isatty, otherwise UTC string
0.2.0 / 2012-01-22
==================
* Added wildcard support
0.1.0 / 2011-12-02
==================
* Added: remove colors unless stderr isatty [TooTallNate]
0.0.1 / 2010-01-03
==================
* Initial release
# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
# BIN directory
BIN := $(THIS_DIR)/node_modules/.bin
# applications
NODE ?= $(shell which node)
NPM ?= $(NODE) $(shell which npm)
BROWSERIFY ?= $(NODE) $(BIN)/browserify
all: dist/debug.js
install: node_modules
clean:
@rm -rf node_modules dist
dist:
@mkdir -p $@
dist/debug.js: node_modules browser.js debug.js dist
@$(BROWSERIFY) \
--standalone debug \
. > $@
node_modules: package.json
@NODE_ENV= $(NPM) install
@touch node_modules
.PHONY: all install clean
# debug
tiny node.js debugging utility modelled after node core's debugging technique.
## Installation
```bash
$ npm install debug
```
## Usage
With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
Example _app.js_:
```js
var debug = require('debug')('http')
, http = require('http')
, name = 'My App';
// fake app
debug('booting %s', name);
http.createServer(function(req, res){
debug(req.method + ' ' + req.url);
res.end('hello\n');
}).listen(3000, function(){
debug('listening');
});
// fake worker of some kind
require('./worker');
```
Example _worker.js_:
```js
var debug = require('debug')('worker');
setInterval(function(){
debug('doing some work');
}, 1000);
```
The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
#### Windows note
On Windows the environment variable is set using the `set` command.
```cmd
set DEBUG=*,-not_this
```
Then, run the program to be debugged as ususal.
## Millisecond diff
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
## Conventions
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
## Wildcards
The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
## Browser support
Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`.
```js
a = debug('worker:a');
b = debug('worker:b');
setInterval(function(){
a('doing some work');
}, 1000);
setInterval(function(){
b('doing some work');
}, 1200);
```
#### Web Inspector Colors
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
option. These are WebKit web inspectors, Firefox ([since version
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
and the Firebug plugin for Firefox (any version).
Colored output looks something like:
![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
### stderr vs stdout
You can set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally:
Example _stderr.js_:
```js
var debug = require('../');
var log = debug('app:log');
// by default console.log is used
log('goes to stdout!');
var error = debug('app:error');
// set this namespace to log via console.error
error.log = console.error.bind(console); // don't forget to bind to console!
error('goes to stderr');
log('still goes to stdout!');
// set all output to go via console.warn
// overrides all per-namespace log settings
debug.log = console.warn.bind(console);
log('now goes to stderr via console.warn');
error('still goes to stderr, but via console.warn now');
```
## Authors
- TJ Holowaychuk
- Nathan Rajlich
## License
(The MIT License)
Copyright (c) 2014 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
"name": "visionmedia/debug",
"main": "dist/debug.js",
"version": "2.1.1",
"homepage": "https://github.com/visionmedia/debug",
"authors": [
"TJ Holowaychuk <tj@vision-media.ca>"
],
"description": "visionmedia/debug",
"moduleType": [
"amd",
"es6",
"globals",
"node"
],
"keywords": [
"visionmedia",
"debug"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
/**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = require('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
/**
* Use chrome.storage.local if we are in an app
*/
var storage;
if (typeof chrome !== 'undefined' && typeof chrome.storage !== 'undefined')
storage = chrome.storage.local;
else
storage = window.localStorage;
/**
* Colors.
*/
exports.colors = [
'lightseagreen',
'forestgreen',
'goldenrod',
'dodgerblue',
'darkorchid',
'crimson'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
function useColors() {
// is webkit? http://stackoverflow.com/a/16459606/376773
return ('WebkitAppearance' in document.documentElement.style) ||
// is firebug? http://stackoverflow.com/a/398120/376773
(window.console && (console.firebug || (console.exception && console.table))) ||
// is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
exports.formatters.j = function(v) {
return JSON.stringify(v);
};
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs() {
var args = arguments;
var useColors = this.useColors;
args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
if (!useColors) return args;
var c = 'color: ' + this.color;
args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-z%]/g, function(match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
// we only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
return args;
}
/**
* Invokes `console.log()` when available.
* No-op when `console.log` is not a "function".
*
* @api public
*/
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
return 'object' === typeof console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (null == namespaces) {
storage.removeItem('debug');
} else {
storage.debug = namespaces;
}
} catch(e) {}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
var r;
try {
r = storage.debug;
} catch(e) {}
return r;
}
/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
exports.enable(load());
{
"name": "debug",
"repo": "visionmedia/debug",
"description": "small debugging utility",
"version": "2.1.1",
"keywords": [
"debug",
"log",
"debugger"
],
"main": "browser.js",
"scripts": [
"browser.js",
"debug.js"
],
"dependencies": {
"guille/ms.js": "0.6.1"
}
}
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = require('ms');
/**
* The currently active debug mode names, and names to skip.
*/
exports.names = [];
exports.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lowercased letter, i.e. "n".
*/
exports.formatters = {};
/**
* Previously assigned color.
*/
var prevColor = 0;
/**
* Previous log timestamp.
*/
var prevTime;
/**
* Select a color.
*
* @return {Number}
* @api private
*/
function selectColor() {
return exports.colors[prevColor++ % exports.colors.length];
}
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function debug(namespace) {
// define the `disabled` version
function disabled() {
}
disabled.enabled = false;
// define the `enabled` version
function enabled() {
var self = enabled;
// set `diff` timestamp
var curr = +new Date();
var ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
// add the `color` if not set
if (null == self.useColors) self.useColors = exports.useColors();
if (null == self.color && self.useColors) self.color = selectColor();
var args = Array.prototype.slice.call(arguments);
args[0] = exports.coerce(args[0]);
if ('string' !== typeof args[0]) {
// anything else let's inspect with %o
args = ['%o'].concat(args);
}
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
if ('function' === typeof exports.formatArgs) {
args = exports.formatArgs.apply(self, args);
}
var logFn = enabled.log || exports.log || console.log.bind(console);
logFn.apply(self, args);
}
enabled.enabled = true;
var fn = exports.enabled(namespace) ? enabled : disabled;
fn.namespace = namespace;
return fn;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
exports.save(namespaces);
var split = (namespaces || '').split(/[\s,]+/);
var len = split.length;
for (var i = 0; i < len; i++) {
if (!split[i]) continue; // ignore empty strings
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @api public
*/
function disable() {
exports.enable('');
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
var i, len;
for (i = 0, len = exports.skips.length; i < len; i++) {
if (exports.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = exports.names.length; i < len; i++) {
if (exports.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
/**
* Module dependencies.
*/
var tty = require('tty');
var util = require('util');
/**
* This is the Node.js implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = require('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
/**
* Colors.
*/
exports.colors = [6, 2, 3, 4, 5, 1];
/**
* The file descriptor to write the `debug()` calls to.
* Set the `DEBUG_FD` env variable to override with another value. i.e.:
*
* $ DEBUG_FD=3 node script.js 3>debug.log
*/
var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
var stream = 1 === fd ? process.stdout :
2 === fd ? process.stderr :
createWritableStdioStream(fd);
/**
* Is stdout a TTY? Colored output is enabled when `true`.
*/
function useColors() {
var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase();
if (0 === debugColors.length) {
return tty.isatty(fd);
} else {
return '0' !== debugColors
&& 'no' !== debugColors
&& 'false' !== debugColors
&& 'disabled' !== debugColors;
}
}
/**
* Map %o to `util.inspect()`, since Node doesn't do that out of the box.
*/
var inspect = (4 === util.inspect.length ?
// node <= 0.8.x
function (v, colors) {
return util.inspect(v, void 0, void 0, colors);
} :
// node > 0.8.x
function (v, colors) {
return util.inspect(v, { colors: colors });
}
);
exports.formatters.o = function(v) {
return inspect(v, this.useColors)
.replace(/\s*\n\s*/g, ' ');
};
/**
* Adds ANSI color escape codes if enabled.
*
* @api public
*/
function formatArgs() {
var args = arguments;
var useColors = this.useColors;
var name = this.namespace;
if (useColors) {
var c = this.color;
args[0] = ' \u001b[9' + c + 'm' + name + ' '
+ '\u001b[0m'
+ args[0] + '\u001b[3' + c + 'm'
+ ' +' + exports.humanize(this.diff) + '\u001b[0m';
} else {
args[0] = new Date().toUTCString()
+ ' ' + name + ' ' + args[0];
}
return args;
}
/**
* Invokes `console.error()` with the specified arguments.
*/
function log() {
return stream.write(util.format.apply(this, arguments) + '\n');
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
if (null == namespaces) {
// If you set a process.env field to null or undefined, it gets cast to the
// string 'null' or 'undefined'. Just delete instead.
delete process.env.DEBUG;
} else {
process.env.DEBUG = namespaces;
}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
return process.env.DEBUG;
}
/**
* Copied from `node/src/node.js`.
*
* XXX: It's lame that node doesn't expose this API out-of-the-box. It also
* relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
*/
function createWritableStdioStream (fd) {
var stream;
var tty_wrap = process.binding('tty_wrap');
// Note stream._type is used for test-module-load-list.js
switch (tty_wrap.guessHandleType(fd)) {
case 'TTY':
stream = new tty.WriteStream(fd);
stream._type = 'tty';
// Hack to have stream not keep the event loop alive.
// See https://github.com/joyent/node/issues/1726
if (stream._handle && stream._handle.unref) {
stream._handle.unref();
}
break;
case 'FILE':
var fs = require('fs');
stream = new fs.SyncWriteStream(fd, { autoClose: false });
stream._type = 'fs';
break;
case 'PIPE':
case 'TCP':
var net = require('net');
stream = new net.Socket({
fd: fd,
readable: false,
writable: true
});
// FIXME Should probably have an option in net.Socket to create a
// stream from an existing fd which is writable only. But for now
// we'll just add this hack and set the `readable` member to false.
// Test: ./node test/fixtures/echo.js < /etc/passwd
stream.readable = false;
stream.read = null;
stream._type = 'pipe';
// FIXME Hack to have stream not keep the event loop alive.
// See https://github.com/joyent/node/issues/1726
if (stream._handle && stream._handle.unref) {
stream._handle.unref();
}
break;
default:
// Probably an error on in uv_guess_handle()
throw new Error('Implement me. Unknown stream file type!');
}
// For supporting legacy API we put the FD here.
stream.fd = fd;
stream._isStdio = true;
return stream;
}
/**
* Enable namespaces listed in `process.env.DEBUG` initially.
*/
exports.enable(load());
# ms.js: miliseconds conversion utility
```js
ms('1d') // 86400000
ms('10h') // 36000000
ms('2h') // 7200000
ms('1m') // 60000
ms('5s') // 5000
ms('100') // 100
```
```js
ms(60000) // "1m"
ms(2 * 60000) // "2m"
ms(ms('10 hours')) // "10h"
```
```js
ms(60000, { long: true }) // "1 minute"
ms(2 * 60000, { long: true }) // "2 minutes"
ms(ms('10 hours', { long: true })) // "10 hours"
```
- Node/Browser compatible. Published as `ms` in NPM.
- If a number is supplied to `ms`, a string with a unit is returned.
- If a string that contains the number is supplied, it returns it as
a number (e.g: it returns `100` for `'100'`).
- If you pass a string with a number and a valid unit, the number of
equivalent ms is returned.
## License
MIT
\ No newline at end of file
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} options
* @return {String|Number}
* @api public
*/
module.exports = function(val, options){
options = options || {};
if ('string' == typeof val) return parse(val);
return options.long
? long(val)
: short(val);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
if (!match) return;
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'y':
return n * y;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 's':
return n * s;
case 'ms':
return n;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function short(ms) {
if (ms >= d) return Math.round(ms / d) + 'd';
if (ms >= h) return Math.round(ms / h) + 'h';
if (ms >= m) return Math.round(ms / m) + 'm';
if (ms >= s) return Math.round(ms / s) + 's';
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function long(ms) {
return plural(ms, d, 'day')
|| plural(ms, h, 'hour')
|| plural(ms, m, 'minute')
|| plural(ms, s, 'second')
|| ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, n, name) {
if (ms < n) return;
if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
return Math.ceil(ms / n) + ' ' + name + 's';
}
{
"name": "ms",
"version": "0.6.2",
"description": "Tiny ms conversion utility",
"repository": {
"type": "git",
"url": "git://github.com/guille/ms.js.git"
},
"main": "./index",
"devDependencies": {
"mocha": "*",
"expect.js": "*",
"serve": "*"
},
"component": {
"scripts": {
"ms/index.js": "index.js"
}
},
"bugs": {
"url": "https://github.com/guille/ms.js/issues"
},
"_id": "ms@0.6.2",
"dist": {
"shasum": "d89c2124c6fdc1353d65a8b77bf1aac4b193708c",
"tarball": "http://registry.npmjs.org/ms/-/ms-0.6.2.tgz"
},
"_from": "ms@0.6.2",
"_npmVersion": "1.2.30",
"_npmUser": {
"name": "rauchg",
"email": "rauchg@gmail.com"
},
"maintainers": [
{
"name": "rauchg",
"email": "rauchg@gmail.com"
}
],
"directories": {},
"_shasum": "d89c2124c6fdc1353d65a8b77bf1aac4b193708c",
"_resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
"readme": "ERROR: No README data found!",
"scripts": {}
}
{
"name": "debug",
"version": "2.1.1",
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
},
"description": "small debugging utility",
"keywords": [
"debug",
"log",
"debugger"
],
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
},
"contributors": [
{
"name": "Nathan Rajlich",
"email": "nathan@tootallnate.net",
"url": "http://n8.io"
}
],
"license": "MIT",
"dependencies": {
"ms": "0.6.2"
},
"devDependencies": {
"browserify": "6.1.0",
"mocha": "*"
},
"main": "./node.js",
"browser": "./browser.js",
"component": {
"scripts": {
"debug/index.js": "browser.js",
"debug/debug.js": "debug.js"
}
},
"gitHead": "24cc5c04fc8886fa9afcadea4db439f9a6186ca4",
"bugs": {
"url": "https://github.com/visionmedia/debug/issues"
},
"homepage": "https://github.com/visionmedia/debug",
"_id": "debug@2.1.1",
"scripts": {},
"_shasum": "e0c548cc607adc22b537540dc3639c4236fdf90c",
"_from": "debug@~2.1.1",
"_npmVersion": "1.4.28",
"_npmUser": {
"name": "tootallnate",
"email": "nathan@tootallnate.net"
},
"maintainers": [
{
"name": "tjholowaychuk",
"email": "tj@vision-media.ca"
},
{
"name": "tootallnate",
"email": "nathan@tootallnate.net"
}
],
"dist": {
"shasum": "e0c548cc607adc22b537540dc3639c4236fdf90c",
"tarball": "http://registry.npmjs.org/debug/-/debug-2.1.1.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/debug/-/debug-2.1.1.tgz",
"readme": "ERROR: No README data found!"
}
1.0.0 / 2014-08-10
==================
* Honor `res.statusCode` change in `listener`
* Move to `jshttp` orgainzation
* Prevent `arguments`-related de-opt
0.0.0 / 2014-05-13
==================
* Initial implementation
(The MIT License)
Copyright (c) 2014 Douglas Christopher Wilson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# on-headers
[![NPM Version](https://img.shields.io/npm/v/on-headers.svg?style=flat)](https://www.npmjs.org/package/on-headers)
[![Node.js Version](https://img.shields.io/badge/node.js->=_0.8-blue.svg?style=flat)](http://nodejs.org/download/)
[![Build Status](https://img.shields.io/travis/jshttp/on-headers.svg?style=flat)](https://travis-ci.org/jshttp/on-headers)
[![Coverage Status](https://img.shields.io/coveralls/jshttp/on-headers.svg?style=flat)](https://coveralls.io/r/jshttp/on-headers)
[![Gittip](https://img.shields.io/gittip/dougwilson.svg?style=flat)](https://www.gittip.com/dougwilson/)
Execute a listener when a response is about to write headers.
## Install
```sh
$ npm install on-headers
```
## API
```js
var onHeaders = require('on-headers')
```
### onHeaders(res, listener)
This will add the listener `listener` to fire when headers are emitted for `res`.
The listener is passed the `response` object as it's context (`this`). Headers are
considered to be emitted only once, right before they are sent to the client.
When this is called multiple times on the same `res`, the `listener`s are fired
in the reverse order they were added.
## Examples
```js
var http = require('http')
var onHeaders = require('on-headers')
http
.createServer(onRequest)
.listen(3000)
function addPoweredBy() {
// add if not set by end of request
if (!this.getHeader('X-Powered-By')) {
this.addHeader('X-Powered-By', 'Node.js')
}
}
function onRequest(req, res) {
onHeaders(res, addPoweredBy)
res.setHeader('Content-Type', 'text/plain')
res.end('hello!')
}
```
## License
[MIT](LICENSE)
/*!
* on-headers
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Reference to Array slice.
*/
var slice = Array.prototype.slice
/**
* Execute a listener when a response is about to write headers.
*
* @param {Object} res
* @return {Function} listener
* @api public
*/
module.exports = function onHeaders(res, listener) {
if (!res) {
throw new TypeError('argument res is required')
}
if (typeof listener !== 'function') {
throw new TypeError('argument listener must be a function')
}
res.writeHead = createWriteHead(res.writeHead, listener)
}
function createWriteHead(prevWriteHead, listener) {
var fired = false;
// return function with core name and argument list
return function writeHead(statusCode) {
// set headers from arguments
var args = setWriteHeadHeaders.apply(this, arguments);
// fire listener
if (!fired) {
fired = true
listener.call(this)
// pass-along an updated status code
if (typeof args[0] === 'number' && this.statusCode !== args[0]) {
args[0] = this.statusCode
args.length = 1
}
}
prevWriteHead.apply(this, args);
}
}
function setWriteHeadHeaders(statusCode) {
var length = arguments.length
var headerIndex = length > 1 && typeof arguments[1] === 'string'
? 2
: 1
var headers = length >= headerIndex + 1
? arguments[headerIndex]
: undefined
this.statusCode = statusCode
// the following block is from node.js core
if (Array.isArray(headers)) {
// handle array case
for (var i = 0, len = headers.length; i < len; ++i) {
this.setHeader(headers[i][0], headers[i][1])
}
} else if (headers) {
// handle object case
var keys = Object.keys(headers)
for (var i = 0; i < keys.length; i++) {
var k = keys[i]
if (k) this.setHeader(k, headers[k])
}
}
// copy leading arguments
var args = new Array(Math.min(length, headerIndex))
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i]
}
return args
}
1.0.0 / 2014-08-10
==================
* Accept valid `Vary` header string as `field`
* Add `vary.append` for low-level string manipulation
* Move to `jshttp` orgainzation
0.1.0 / 2014-06-05
==================
* Support array of fields to set
0.0.0 / 2014-06-04
==================
* Initial release
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment