added template for ponysays ensemble composition -- before sstate change to sequencerstate
parent
e22c5abe6a
commit
bef6cf19e4
|
@ -1,3 +0,0 @@
|
||||||
coverage/
|
|
||||||
test/
|
|
||||||
.travis.yml
|
|
|
@ -1,32 +0,0 @@
|
||||||
1.1.1 / 2014-06-20
|
|
||||||
==================
|
|
||||||
|
|
||||||
* deps: accepts@~1.0.4
|
|
||||||
- use `mime-types`
|
|
||||||
|
|
||||||
1.1.0 / 2014-06-16
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Display error on console formatted like `throw`
|
|
||||||
* Escape HTML with `escape-html` module
|
|
||||||
* Escape HTML in stack trace
|
|
||||||
* Escape HTML in title
|
|
||||||
* Fix up edge cases with error sent in response
|
|
||||||
* Set `X-Content-Type-Options: nosniff` header
|
|
||||||
* Use accepts for negotiation
|
|
||||||
|
|
||||||
1.0.2 / 2014-06-05
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Pass on errors from reading error files
|
|
||||||
|
|
||||||
1.0.1 / 2014-04-29
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Clean up error CSS
|
|
||||||
* Do not respond after headers sent
|
|
||||||
|
|
||||||
1.0.0 / 2014-03-03
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Genesis from `connect`
|
|
|
@ -1,27 +1,78 @@
|
||||||
# errorhandler
|
# errorhandler
|
||||||
|
|
||||||
[![NPM version](https://badge.fury.io/js/errorhandler.svg)](http://badge.fury.io/js/errorhandler)
|
[![NPM Version][npm-version-image]][npm-url]
|
||||||
[![Build Status](https://travis-ci.org/expressjs/errorhandler.svg?branch=master)](https://travis-ci.org/expressjs/errorhandler)
|
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/expressjs/errorhandler.svg?branch=master)](https://coveralls.io/r/expressjs/errorhandler)
|
[![Build Status][travis-image]][travis-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
Previously `connect.errorHandler()`.
|
Development-only error handler middleware.
|
||||||
|
|
||||||
|
This middleware is only intended to be used in a development environment, as
|
||||||
|
the _full error stack traces and internal details of any object passed to this
|
||||||
|
module_ will be sent back to the client when an error occurs.
|
||||||
|
|
||||||
|
When an object is provided to Express as an error, this module will display
|
||||||
|
as much about this object as possible, and will do so by using content negotiation
|
||||||
|
for the response between HTML, JSON, and plain text.
|
||||||
|
|
||||||
|
* When the object is a standard `Error` object, the string provided by the
|
||||||
|
`stack` property will be returned in HTML/text responses.
|
||||||
|
* When the object is a non-`Error` object, the result of
|
||||||
|
[util.inspect](https://nodejs.org/api/util.html#util_util_inspect_object_options)
|
||||||
|
will be returned in HTML/text responses.
|
||||||
|
* For JSON responses, the result will be an object with all enumerable properties
|
||||||
|
from the object in the response.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ npm install errorhandler
|
$ npm install errorhandler
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
### errorhandler()
|
<!-- eslint-disable no-unused-vars -->
|
||||||
|
|
||||||
|
```js
|
||||||
|
var errorhandler = require('errorhandler')
|
||||||
|
```
|
||||||
|
|
||||||
|
### errorhandler(options)
|
||||||
|
|
||||||
Create new middleware to handle errors and respond with content negotiation.
|
Create new middleware to handle errors and respond with content negotiation.
|
||||||
This middleware is only intended to be used in a development environment, as
|
|
||||||
the full error stack traces will be send back to the client when an error
|
|
||||||
occurs.
|
|
||||||
|
|
||||||
## Example
|
#### Options
|
||||||
|
|
||||||
|
Error handler accepts these properties in the options object.
|
||||||
|
|
||||||
|
##### log
|
||||||
|
|
||||||
|
Provide a function to be called with the error and a string representation of
|
||||||
|
the error. Can be used to write the error to any desired location, or set to
|
||||||
|
`false` to only send the error back in the response. Called as
|
||||||
|
`log(err, str, req, res)` where `err` is the `Error` object, `str` is a string
|
||||||
|
representation of the error, `req` is the request object and `res` is the
|
||||||
|
response object (note, this function is invoked _after_ the response has been
|
||||||
|
written).
|
||||||
|
|
||||||
|
The default value for this option is `true` unless `process.env.NODE_ENV === 'test'`.
|
||||||
|
|
||||||
|
Possible values:
|
||||||
|
|
||||||
|
* `true`: Log errors using `console.error(str)`.
|
||||||
|
* `false`: Only send the error back in the response.
|
||||||
|
* A function: pass the error to a function for handling.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Simple example
|
||||||
|
|
||||||
|
Basic example of adding this middleware as the error handler only in development
|
||||||
|
with `connect` (`express` also can be used in this example).
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var connect = require('connect')
|
var connect = require('connect')
|
||||||
|
@ -30,30 +81,48 @@ var errorhandler = require('errorhandler')
|
||||||
var app = connect()
|
var app = connect()
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
// only use in development
|
||||||
app.use(errorhandler())
|
app.use(errorhandler())
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Custom output location
|
||||||
|
|
||||||
|
Sometimes you may want to output the errors to a different location than STDERR
|
||||||
|
during development, like a system notification, for example.
|
||||||
|
|
||||||
|
<!-- eslint-disable handle-callback-err -->
|
||||||
|
|
||||||
|
```js
|
||||||
|
var connect = require('connect')
|
||||||
|
var errorhandler = require('errorhandler')
|
||||||
|
var notifier = require('node-notifier')
|
||||||
|
|
||||||
|
var app = connect()
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
// only use in development
|
||||||
|
app.use(errorhandler({ log: errorNotification }))
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorNotification (err, str, req) {
|
||||||
|
var title = 'Error in ' + req.method + ' ' + req.url
|
||||||
|
|
||||||
|
notifier.notify({
|
||||||
|
title: title,
|
||||||
|
message: str
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The MIT License (MIT)
|
[MIT](LICENSE)
|
||||||
|
|
||||||
Copyright (c) 2014 Jonathan Ong me@jongleberry.com
|
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/errorhandler/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/errorhandler?branch=master
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
[npm-downloads-image]: https://badgen.net/npm/dm/errorhandler
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
[npm-url]: https://npmjs.org/package/errorhandler
|
||||||
in the Software without restriction, including without limitation the rights
|
[npm-version-image]: https://badgen.net/npm/v/errorhandler
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
[travis-image]: https://badgen.net/travis/expressjs/errorhandler/master
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
[travis-url]: https://travis-ci.org/expressjs/errorhandler
|
||||||
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.
|
|
||||||
|
|
|
@ -2,16 +2,40 @@
|
||||||
* errorhandler
|
* errorhandler
|
||||||
* Copyright(c) 2010 Sencha Inc.
|
* Copyright(c) 2010 Sencha Inc.
|
||||||
* Copyright(c) 2011 TJ Holowaychuk
|
* Copyright(c) 2011 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2014 Jonathan Ong
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
* MIT Licensed
|
* MIT Licensed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var accepts = require('accepts')
|
var accepts = require('accepts')
|
||||||
var escapeHtml = require('escape-html');
|
var escapeHtml = require('escape-html')
|
||||||
var fs = require('fs');
|
var fs = require('fs')
|
||||||
|
var path = require('path')
|
||||||
|
var util = require('util')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DOUBLE_SPACE_REGEXP = /\x20{2}/g
|
||||||
|
var NEW_LINE_REGEXP = /\n/g
|
||||||
|
var STYLESHEET = fs.readFileSync(path.join(__dirname, '/public/style.css'), 'utf8')
|
||||||
|
var TEMPLATE = fs.readFileSync(path.join(__dirname, '/public/error.html'), 'utf8')
|
||||||
|
var inspect = util.inspect
|
||||||
|
var toString = Object.prototype.toString
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
var defer = typeof setImmediate === 'function'
|
||||||
|
? setImmediate
|
||||||
|
: function (fn) { process.nextTick(fn.bind.apply(fn, arguments)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error handler:
|
* Error handler:
|
||||||
|
@ -38,11 +62,33 @@ var fs = require('fs');
|
||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports = module.exports = function errorHandler(){
|
exports = module.exports = function errorHandler (options) {
|
||||||
// get environment
|
// get environment
|
||||||
var env = process.env.NODE_ENV || 'development'
|
var env = process.env.NODE_ENV || 'development'
|
||||||
|
|
||||||
return function errorHandler(err, req, res, next){
|
// get options
|
||||||
|
var opts = options || {}
|
||||||
|
|
||||||
|
// get log option
|
||||||
|
var log = opts.log === undefined
|
||||||
|
? env !== 'test'
|
||||||
|
: opts.log
|
||||||
|
|
||||||
|
if (typeof log !== 'function' && typeof log !== 'boolean') {
|
||||||
|
throw new TypeError('option log must be function or boolean')
|
||||||
|
}
|
||||||
|
|
||||||
|
// default logging using console.error
|
||||||
|
if (log === true) {
|
||||||
|
log = logerror
|
||||||
|
}
|
||||||
|
|
||||||
|
return function errorHandler (err, req, res, next) {
|
||||||
|
// respect err.statusCode
|
||||||
|
if (err.statusCode) {
|
||||||
|
res.statusCode = err.statusCode
|
||||||
|
}
|
||||||
|
|
||||||
// respect err.status
|
// respect err.status
|
||||||
if (err.status) {
|
if (err.status) {
|
||||||
res.statusCode = err.status
|
res.statusCode = err.status
|
||||||
|
@ -53,9 +99,10 @@ exports = module.exports = function errorHandler(){
|
||||||
res.statusCode = 500
|
res.statusCode = 500
|
||||||
}
|
}
|
||||||
|
|
||||||
// write error to console
|
// log the error
|
||||||
if (env !== 'test') {
|
var str = stringify(err)
|
||||||
console.error(err.stack || String(err))
|
if (log) {
|
||||||
|
defer(log, err, str, req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cannot actually respond
|
// cannot actually respond
|
||||||
|
@ -65,47 +112,87 @@ exports = module.exports = function errorHandler(){
|
||||||
|
|
||||||
// negotiate
|
// negotiate
|
||||||
var accept = accepts(req)
|
var accept = accepts(req)
|
||||||
var type = accept.types('html', 'json', 'text')
|
var type = accept.type('html', 'json', 'text')
|
||||||
|
|
||||||
// Security header for content sniffing
|
// Security header for content sniffing
|
||||||
res.setHeader('X-Content-Type-Options', 'nosniff')
|
res.setHeader('X-Content-Type-Options', 'nosniff')
|
||||||
|
|
||||||
// html
|
// html
|
||||||
if (type === 'html') {
|
if (type === 'html') {
|
||||||
fs.readFile(__dirname + '/public/style.css', 'utf8', function(e, style){
|
var isInspect = !err.stack && String(err) === toString.call(err)
|
||||||
if (e) return next(e);
|
var errorHtml = !isInspect
|
||||||
fs.readFile(__dirname + '/public/error.html', 'utf8', function(e, html){
|
? escapeHtmlBlock(str.split('\n', 1)[0] || 'Error')
|
||||||
if (e) return next(e);
|
: 'Error'
|
||||||
var stack = (err.stack || '')
|
var stack = !isInspect
|
||||||
.split('\n').slice(1)
|
? String(str).split('\n').slice(1)
|
||||||
.map(function(v){ return '<li>' + escapeHtml(v).replace(/ /g, ' ') + '</li>'; }).join('');
|
: [str]
|
||||||
html = html
|
var stackHtml = stack
|
||||||
.replace('{style}', style)
|
.map(function (v) { return '<li>' + escapeHtmlBlock(v) + '</li>' })
|
||||||
.replace('{stack}', stack)
|
.join('')
|
||||||
.replace('{title}', escapeHtml(exports.title))
|
var body = TEMPLATE
|
||||||
.replace('{statusCode}', res.statusCode)
|
.replace('{style}', STYLESHEET)
|
||||||
.replace(/\{error\}/g, escapeHtml(String(err)).replace(/ /g, ' ').replace(/\n/g, '<br>'));
|
.replace('{stack}', stackHtml)
|
||||||
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
.replace('{title}', escapeHtml(exports.title))
|
||||||
res.end(html);
|
.replace('{statusCode}', res.statusCode)
|
||||||
});
|
.replace(/\{error\}/g, errorHtml)
|
||||||
});
|
res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
res.end(body)
|
||||||
// json
|
// json
|
||||||
} else if (type === 'json') {
|
} else if (type === 'json') {
|
||||||
var error = { message: err.message, stack: err.stack };
|
var error = { message: err.message, stack: err.stack }
|
||||||
for (var prop in err) error[prop] = err[prop];
|
for (var prop in err) error[prop] = err[prop]
|
||||||
var json = JSON.stringify({ error: error });
|
var json = JSON.stringify({ error: error }, null, 2)
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
||||||
res.end(json);
|
res.end(json)
|
||||||
// plain text
|
// plain text
|
||||||
} else {
|
} else {
|
||||||
res.setHeader('Content-Type', 'text/plain');
|
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
|
||||||
res.end(err.stack || String(err));
|
res.end(str)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template title, framework authors may override this value.
|
* Template title, framework authors may override this value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.title = 'Connect';
|
exports.title = 'Connect'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape a block of HTML, preserving whitespace.
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function escapeHtmlBlock (str) {
|
||||||
|
return escapeHtml(str)
|
||||||
|
.replace(DOUBLE_SPACE_REGEXP, ' ')
|
||||||
|
.replace(NEW_LINE_REGEXP, '<br>')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stringify a value.
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stringify (val) {
|
||||||
|
var stack = val.stack
|
||||||
|
|
||||||
|
if (stack) {
|
||||||
|
return String(stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
var str = String(val)
|
||||||
|
|
||||||
|
return str === toString.call(val)
|
||||||
|
? inspect(val)
|
||||||
|
: str
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log error to console.
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function logerror (err, str) {
|
||||||
|
console.error(str || err.stack)
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
coverage/
|
|
||||||
test/
|
|
||||||
.travis.yml
|
|
|
@ -1,38 +0,0 @@
|
||||||
|
|
||||||
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
|
|
|
@ -1,101 +0,0 @@
|
||||||
# Accepts
|
|
||||||
|
|
||||||
[![NPM version](https://badge.fury.io/js/accepts.svg)](http://badge.fury.io/js/accepts)
|
|
||||||
[![Build Status](https://travis-ci.org/expressjs/accepts.svg?branch=master)](https://travis-ci.org/expressjs/accepts)
|
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/expressjs/accepts.svg?branch=master)](https://coveralls.io/r/expressjs/accepts)
|
|
||||||
|
|
||||||
Higher level content negotation based on [negotiator](https://github.com/federomero/negotiator). Extracted from [koa](https://github.com/koajs/koa) for general use.
|
|
||||||
|
|
||||||
In addition to negotatior, 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 `*`
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### var accept = new Accepts(req)
|
|
||||||
|
|
||||||
```js
|
|
||||||
var accepts = require('accepts')
|
|
||||||
|
|
||||||
http.createServer(function (req, res) {
|
|
||||||
var accept = accepts(req)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### accept\[property\]\(\)
|
|
||||||
|
|
||||||
Returns all the explicitly accepted content property as an array in descending priority.
|
|
||||||
|
|
||||||
- `accept.types()`
|
|
||||||
- `accept.encodings()`
|
|
||||||
- `accept.charsets()`
|
|
||||||
- `accept.languages()`
|
|
||||||
|
|
||||||
They are also aliased in singular form such as `accept.type()`. `accept.languages()` is also aliased as `accept.langs()`, etc.
|
|
||||||
|
|
||||||
Note: you should almost never do this in a real app as it defeats the purpose of content negotiation.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// in Google Chrome
|
|
||||||
var encodings = accept.encodings() // -> ['sdch', 'gzip', 'deflate']
|
|
||||||
```
|
|
||||||
|
|
||||||
Since you probably don't support `sdch`, you should just supply the encodings you support:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var encoding = accept.encodings('gzip', 'deflate') // -> 'gzip', probably
|
|
||||||
```
|
|
||||||
|
|
||||||
### accept\[property\]\(values, ...\)
|
|
||||||
|
|
||||||
You can either have `values` be an array or have an argument list of values.
|
|
||||||
|
|
||||||
If the client does not accept any `values`, `false` will be returned.
|
|
||||||
If the client accepts any `values`, the preferred `value` will be return.
|
|
||||||
|
|
||||||
For `accept.types()`, shorthand mime types are allowed.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// req.headers.accept = 'application/json'
|
|
||||||
|
|
||||||
accept.types('json') // -> 'json'
|
|
||||||
accept.types('html', 'json') // -> 'json'
|
|
||||||
accept.types('html') // -> false
|
|
||||||
|
|
||||||
// req.headers.accept = ''
|
|
||||||
// which is equivalent to `*`
|
|
||||||
|
|
||||||
accept.types() // -> [], no explicit types
|
|
||||||
accept.types('text/html', 'text/json') // -> 'text/html', since it was first
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2013 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.
|
|
|
@ -1,160 +0,0 @@
|
||||||
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).filter(validMime);
|
|
||||||
var accepts = n.mediaTypes(mimes);
|
|
||||||
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';
|
|
||||||
}
|
|
14
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/.npmignore
generated
vendored
14
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/.npmignore
generated
vendored
|
@ -1,14 +0,0 @@
|
||||||
test
|
|
||||||
build.js
|
|
||||||
|
|
||||||
# OS generated files #
|
|
||||||
######################
|
|
||||||
.DS_Store*
|
|
||||||
# Icon?
|
|
||||||
ehthumbs.db
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Node.js #
|
|
||||||
###########
|
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
12
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/.travis.yml
generated
vendored
12
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/.travis.yml
generated
vendored
|
@ -1,12 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "0.8"
|
|
||||||
- "0.10"
|
|
||||||
- "0.11"
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- node_js: "0.11"
|
|
||||||
fast_finish: true
|
|
||||||
before_install:
|
|
||||||
# remove build script deps before install
|
|
||||||
- node -pe 'f="./package.json";p=require(f);d=p.devDependencies;for(k in d){if("co"===k.substr(0,2))delete d[k]}require("fs").writeFileSync(f,JSON.stringify(p,null,2))'
|
|
22
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/LICENSE
generated
vendored
22
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/LICENSE
generated
vendored
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
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.
|
|
9
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/Makefile
generated
vendored
9
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/Makefile
generated
vendored
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
build:
|
|
||||||
node --harmony-generators build.js
|
|
||||||
|
|
||||||
test:
|
|
||||||
node test/mime.js
|
|
||||||
mocha --require should --reporter spec test/test.js
|
|
||||||
|
|
||||||
.PHONY: build test
|
|
101
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/README.md
generated
vendored
101
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/README.md
generated
vendored
|
@ -1,101 +0,0 @@
|
||||||
# mime-types
|
|
||||||
[![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types)
|
|
||||||
|
|
||||||
The ultimate javascript content-type utility.
|
|
||||||
|
|
||||||
### Install
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ npm install mime-types
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 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. Feel free to add more!
|
|
||||||
- Browser support via Browserify and Component by converting lists to JSON files.
|
|
||||||
|
|
||||||
Otherwise, the API is compatible.
|
|
||||||
|
|
||||||
### Adding Types
|
|
||||||
|
|
||||||
If you'd like to add additional types,
|
|
||||||
simply create a PR adding the type to `custom.json` and
|
|
||||||
a reference link to the [sources](SOURCES.md).
|
|
||||||
|
|
||||||
Do __NOT__ edit `mime.json` or `node.json`.
|
|
||||||
Those are pulled using `build.js`.
|
|
||||||
You should only touch `custom.json`.
|
|
||||||
|
|
||||||
## 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'
|
|
||||||
```
|
|
||||||
|
|
||||||
### mime.types[extension] = type
|
|
||||||
|
|
||||||
A map of content-types by extension.
|
|
||||||
|
|
||||||
### mime.extensions[type] = [extensions]
|
|
||||||
|
|
||||||
A map of extensions by content-type.
|
|
||||||
|
|
||||||
### mime.define(types)
|
|
||||||
|
|
||||||
Globally add definitions.
|
|
||||||
`types` must be an object of the form:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
"<content-type>": [extensions...],
|
|
||||||
"<content-type>": [extensions...]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
See the `.json` files in `lib/` for examples.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT](LICENSE)
|
|
17
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/SOURCES.md
generated
vendored
17
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/SOURCES.md
generated
vendored
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
### Sources for custom types
|
|
||||||
|
|
||||||
This is a list of sources for any custom mime types.
|
|
||||||
When adding custom mime types, please link to where you found the mime type,
|
|
||||||
even if it's from an unofficial source.
|
|
||||||
|
|
||||||
- `text/coffeescript` - http://coffeescript.org/#scripts
|
|
||||||
- `text/x-handlebars-template` - https://handlebarsjs.com/#getting-started
|
|
||||||
- `text/x-sass` & `text/x-scss` - https://github.com/janlelis/rubybuntu-mime/blob/master/sass.xml
|
|
||||||
- `text.jsx` - http://facebook.github.io/react/docs/getting-started.html [[2]](https://github.com/facebook/react/blob/f230e0a03154e6f8a616e0da1fb3d97ffa1a6472/vendor/browser-transforms.js#L210)
|
|
||||||
|
|
||||||
[Sources for node.json types](https://github.com/broofa/node-mime/blob/master/types/node.types)
|
|
||||||
|
|
||||||
### Notes on weird types
|
|
||||||
|
|
||||||
- `font/opentype` - This type is technically invalid according to the spec. No valid types begin with `font/`. No-one uses the official type of `application/vnd.ms-opentype` as the community standardized `application/x-font-otf`. However, chrome logs nonsense warnings unless opentype fonts are served with `font/opentype`. [[1]](http://stackoverflow.com/questions/2871655/proper-mime-type-for-fonts)
|
|
16
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/component.json
generated
vendored
16
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/component.json
generated
vendored
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "mime-types",
|
|
||||||
"description": "The ultimate javascript content-type utility.",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"author": {
|
|
||||||
"name": "Jonathan Ong",
|
|
||||||
"email": "me@jongleberry.com",
|
|
||||||
"url": "http://jongleberry.com",
|
|
||||||
"twitter": "https://twitter.com/jongleberry"
|
|
||||||
},
|
|
||||||
"repository": "expressjs/mime-types",
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"scripts": ["lib/index.js"],
|
|
||||||
"json": ["mime.json", "node.json", "custom.json"]
|
|
||||||
}
|
|
27
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/custom.json
generated
vendored
27
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/custom.json
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"text/jade": [
|
|
||||||
"jade"
|
|
||||||
],
|
|
||||||
"text/stylus": [
|
|
||||||
"stylus",
|
|
||||||
"styl"
|
|
||||||
],
|
|
||||||
"text/less": [
|
|
||||||
"less"
|
|
||||||
],
|
|
||||||
"text/x-sass": [
|
|
||||||
"sass"
|
|
||||||
],
|
|
||||||
"text/x-scss": [
|
|
||||||
"scss"
|
|
||||||
],
|
|
||||||
"text/coffeescript": [
|
|
||||||
"coffee"
|
|
||||||
],
|
|
||||||
"text/x-handlebars-template": [
|
|
||||||
"hbs"
|
|
||||||
],
|
|
||||||
"text/jsx": [
|
|
||||||
"jsx"
|
|
||||||
]
|
|
||||||
}
|
|
74
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/index.js
generated
vendored
74
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/index.js
generated
vendored
|
@ -1,74 +0,0 @@
|
||||||
|
|
||||||
// types[extension] = type
|
|
||||||
exports.types = Object.create(null)
|
|
||||||
// extensions[type] = [extensions]
|
|
||||||
exports.extensions = Object.create(null)
|
|
||||||
// define more mime types
|
|
||||||
exports.define = define
|
|
||||||
|
|
||||||
// store the json files
|
|
||||||
exports.json = {
|
|
||||||
mime: require('./mime.json'),
|
|
||||||
node: require('./node.json'),
|
|
||||||
custom: require('./custom.json'),
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.lookup = function (string) {
|
|
||||||
if (!string || typeof string !== "string") return false
|
|
||||||
string = string.replace(/.*[\.\/\\]/, '').toLowerCase()
|
|
||||||
if (!string) return false
|
|
||||||
return exports.types[string] || false
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.extension = function (type) {
|
|
||||||
if (!type || typeof type !== "string") return false
|
|
||||||
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) {
|
|
||||||
// special cases
|
|
||||||
switch (type) {
|
|
||||||
case 'application/json': return 'UTF-8'
|
|
||||||
}
|
|
||||||
|
|
||||||
// default text/* to utf-8
|
|
||||||
if (/^text\//.test(type)) return 'UTF-8'
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// backwards compatibility
|
|
||||||
exports.charsets = {
|
|
||||||
lookup: exports.charset
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
define(exports.json.mime)
|
|
||||||
define(exports.json.node)
|
|
||||||
define(exports.json.custom)
|
|
||||||
|
|
||||||
function define(json) {
|
|
||||||
Object.keys(json).forEach(function (type) {
|
|
||||||
var exts = json[type] || []
|
|
||||||
exports.extensions[type] = exports.extensions[type] || []
|
|
||||||
exts.forEach(function (ext) {
|
|
||||||
if (!~exports.extensions[type].indexOf(ext)) exports.extensions[type].push(ext)
|
|
||||||
exports.types[ext] = type
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
3317
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/mime.json
generated
vendored
3317
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/mime.json
generated
vendored
File diff suppressed because it is too large
Load Diff
55
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/node.json
generated
vendored
55
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/lib/node.json
generated
vendored
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"text/vtt": [
|
|
||||||
"vtt"
|
|
||||||
],
|
|
||||||
"application/x-chrome-extension": [
|
|
||||||
"crx"
|
|
||||||
],
|
|
||||||
"text/x-component": [
|
|
||||||
"htc"
|
|
||||||
],
|
|
||||||
"text/cache-manifest": [
|
|
||||||
"manifest"
|
|
||||||
],
|
|
||||||
"application/octet-stream": [
|
|
||||||
"buffer"
|
|
||||||
],
|
|
||||||
"application/mp4": [
|
|
||||||
"m4p"
|
|
||||||
],
|
|
||||||
"audio/mp4": [
|
|
||||||
"m4a"
|
|
||||||
],
|
|
||||||
"video/MP2T": [
|
|
||||||
"ts"
|
|
||||||
],
|
|
||||||
"application/x-web-app-manifest+json": [
|
|
||||||
"webapp"
|
|
||||||
],
|
|
||||||
"text/x-lua": [
|
|
||||||
"lua"
|
|
||||||
],
|
|
||||||
"application/x-lua-bytecode": [
|
|
||||||
"luac"
|
|
||||||
],
|
|
||||||
"text/x-markdown": [
|
|
||||||
"markdown",
|
|
||||||
"md",
|
|
||||||
"mkd"
|
|
||||||
],
|
|
||||||
"text/plain": [
|
|
||||||
"ini"
|
|
||||||
],
|
|
||||||
"application/dash+xml": [
|
|
||||||
"mdp"
|
|
||||||
],
|
|
||||||
"font/opentype": [
|
|
||||||
"otf"
|
|
||||||
],
|
|
||||||
"application/json": [
|
|
||||||
"map"
|
|
||||||
],
|
|
||||||
"application/xml": [
|
|
||||||
"xsd"
|
|
||||||
]
|
|
||||||
}
|
|
42
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/package.json
generated
vendored
42
node_modules/errorhandler/node_modules/accepts/node_modules/mime-types/package.json
generated
vendored
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"name": "mime-types",
|
|
||||||
"description": "The ultimate javascript content-type utility.",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"author": {
|
|
||||||
"name": "Jonathan Ong",
|
|
||||||
"email": "me@jongleberry.com",
|
|
||||||
"url": "http://jongleberry.com"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Jeremiah Senkpiel",
|
|
||||||
"email": "fishrock123@rocketmail.com",
|
|
||||||
"url": "https://searchbeam.jit.su"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/expressjs/mime-types"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "lib",
|
|
||||||
"devDependencies": {
|
|
||||||
"co": "3",
|
|
||||||
"cogent": "0",
|
|
||||||
"mocha": "1",
|
|
||||||
"should": "3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "make test"
|
|
||||||
},
|
|
||||||
"readme": "# mime-types\n[![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types)\n\nThe ultimate javascript content-type utility.\n\n### Install\n\n```sh\n$ npm install mime-types\n```\n\n#### Similar to [node-mime](https://github.com/broofa/node-mime), except:\n\n- __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'`.\n- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.\n- Additional mime types are added such as jade and stylus. Feel free to add more!\n- Browser support via Browserify and Component by converting lists to JSON files.\n\nOtherwise, the API is compatible.\n\n### Adding Types\n\nIf you'd like to add additional types,\nsimply create a PR adding the type to `custom.json` and\na reference link to the [sources](SOURCES.md).\n\nDo __NOT__ edit `mime.json` or `node.json`.\nThose are pulled using `build.js`.\nYou should only touch `custom.json`.\n\n## API\n\n```js\nvar mime = require('mime-types')\n```\n\nAll functions return `false` if input is invalid or not found.\n\n### mime.lookup(path)\n\nLookup the content-type associated with a file.\n\n```js\nmime.lookup('json') // 'application/json'\nmime.lookup('.md') // 'text/x-markdown'\nmime.lookup('file.html') // 'text/html'\nmime.lookup('folder/file.js') // 'application/javascript'\n\nmime.lookup('cats') // false\n```\n\n### mime.contentType(type)\n\nCreate a full content-type header given a content-type or extension.\n\n```js\nmime.contentType('markdown') // 'text/x-markdown; charset=utf-8'\nmime.contentType('file.json') // 'application/json; charset=utf-8'\n```\n\n### mime.extension(type)\n\nGet the default extension for a content-type.\n\n```js\nmime.extension('application/octet-stream') // 'bin'\n```\n\n### mime.charset(type)\n\nLookup the implied default charset of a content-type.\n\n```js\nmime.charset('text/x-markdown') // 'UTF-8'\n```\n\n### mime.types[extension] = type\n\nA map of content-types by extension.\n\n### mime.extensions[type] = [extensions]\n\nA map of extensions by content-type.\n\n### mime.define(types)\n\nGlobally add definitions.\n`types` must be an object of the form:\n\n```js\n{\n \"<content-type>\": [extensions...],\n \"<content-type>\": [extensions...]\n}\n```\n\nSee the `.json` files in `lib/` for examples.\n\n## License\n\n[MIT](LICENSE)\n",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/expressjs/mime-types/issues"
|
|
||||||
},
|
|
||||||
"_id": "mime-types@1.0.1",
|
|
||||||
"_from": "mime-types@~1.0.0"
|
|
||||||
}
|
|
3
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/.npmignore
generated
vendored
3
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/.npmignore
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
examples
|
|
||||||
test
|
|
||||||
.travis.yml
|
|
27
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/LICENSE
generated
vendored
27
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/LICENSE
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
Original "Negotiator" program Copyright Federico Romero
|
|
||||||
Port to JavaScript Copyright Isaac Z. Schlueter
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
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.
|
|
90
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/charset.js
generated
vendored
90
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/charset.js
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
module.exports = preferredCharsets;
|
|
||||||
preferredCharsets.preferredCharsets = preferredCharsets;
|
|
||||||
|
|
||||||
function parseAcceptCharset(accept) {
|
|
||||||
return accept.split(',').map(function(e) {
|
|
||||||
return parseCharset(e.trim());
|
|
||||||
}).filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseCharset(s) {
|
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCharsetPriority(charset, accepted) {
|
|
||||||
return (accepted.map(function(a) {
|
|
||||||
return specify(charset, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q:0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(charset, spec) {
|
|
||||||
var s = 0;
|
|
||||||
if(spec.charset === charset){
|
|
||||||
s |= 1;
|
|
||||||
} else if (spec.charset !== '*' ) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
s: s,
|
|
||||||
q: spec.q,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function preferredCharsets(accept, provided) {
|
|
||||||
// RFC 2616 sec 14.2: no header = *
|
|
||||||
accept = parseAcceptCharset(accept === undefined ? '*' : accept || '');
|
|
||||||
if (provided) {
|
|
||||||
return provided.map(function(type) {
|
|
||||||
return [type, getCharsetPriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type) {
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.charset;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
120
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/encoding.js
generated
vendored
120
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/encoding.js
generated
vendored
|
@ -1,120 +0,0 @@
|
||||||
module.exports = preferredEncodings;
|
|
||||||
preferredEncodings.preferredEncodings = preferredEncodings;
|
|
||||||
|
|
||||||
function parseAcceptEncoding(accept) {
|
|
||||||
var acceptableEncodings;
|
|
||||||
|
|
||||||
if (accept) {
|
|
||||||
acceptableEncodings = accept.split(',').map(function(e) {
|
|
||||||
return parseEncoding(e.trim());
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
acceptableEncodings = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!acceptableEncodings.some(function(e) {
|
|
||||||
return e && specify('identity', e);
|
|
||||||
})) {
|
|
||||||
/*
|
|
||||||
* If identity doesn't explicitly appear in the accept-encoding header,
|
|
||||||
* it's added to the list of acceptable encoding with the lowest q
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
var lowestQ = 1;
|
|
||||||
|
|
||||||
for(var i = 0; i < acceptableEncodings.length; i++){
|
|
||||||
var e = acceptableEncodings[i];
|
|
||||||
if(e && e.q < lowestQ){
|
|
||||||
lowestQ = e.q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acceptableEncodings.push({
|
|
||||||
encoding: 'identity',
|
|
||||||
q: lowestQ / 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return acceptableEncodings.filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseEncoding(s) {
|
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEncodingPriority(encoding, accepted) {
|
|
||||||
return (accepted.map(function(a) {
|
|
||||||
return specify(encoding, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(encoding, spec) {
|
|
||||||
var s = 0;
|
|
||||||
if(spec.encoding === encoding){
|
|
||||||
s |= 1;
|
|
||||||
} else if (spec.encoding !== '*' ) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
s: s,
|
|
||||||
q: spec.q,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function preferredEncodings(accept, provided) {
|
|
||||||
accept = parseAcceptEncoding(accept || '');
|
|
||||||
if (provided) {
|
|
||||||
return provided.map(function(type) {
|
|
||||||
return [type, getEncodingPriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type){
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.encoding;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
103
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/language.js
generated
vendored
103
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/language.js
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
module.exports = preferredLanguages;
|
|
||||||
preferredLanguages.preferredLanguages = preferredLanguages;
|
|
||||||
|
|
||||||
function parseAcceptLanguage(accept) {
|
|
||||||
return accept.split(',').map(function(e) {
|
|
||||||
return parseLanguage(e.trim());
|
|
||||||
}).filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseLanguage(s) {
|
|
||||||
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,
|
|
||||||
full: full
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLanguagePriority(language, accepted) {
|
|
||||||
return (accepted.map(function(a){
|
|
||||||
return specify(language, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(language, spec) {
|
|
||||||
var p = parseLanguage(language)
|
|
||||||
if (!p) return null;
|
|
||||||
var s = 0;
|
|
||||||
if(spec.full === p.full){
|
|
||||||
s |= 4;
|
|
||||||
} else if (spec.prefix === p.full) {
|
|
||||||
s |= 2;
|
|
||||||
} else if (spec.full === p.prefix) {
|
|
||||||
s |= 1;
|
|
||||||
} else if (spec.full !== '*' ) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
s: s,
|
|
||||||
q: spec.q,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function preferredLanguages(accept, provided) {
|
|
||||||
// RFC 2616 sec 14.4: no header = *
|
|
||||||
accept = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
|
|
||||||
if (provided) {
|
|
||||||
|
|
||||||
var ret = provided.map(function(type) {
|
|
||||||
return [type, getLanguagePriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type) {
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.full;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
125
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/mediaType.js
generated
vendored
125
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/mediaType.js
generated
vendored
|
@ -1,125 +0,0 @@
|
||||||
module.exports = preferredMediaTypes;
|
|
||||||
preferredMediaTypes.preferredMediaTypes = preferredMediaTypes;
|
|
||||||
|
|
||||||
function parseAccept(accept) {
|
|
||||||
return accept.split(',').map(function(e) {
|
|
||||||
return parseMediaType(e.trim());
|
|
||||||
}).filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseMediaType(s) {
|
|
||||||
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,
|
|
||||||
full: full
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMediaTypePriority(type, accepted) {
|
|
||||||
return (accepted.map(function(a) {
|
|
||||||
return specify(type, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(type, spec) {
|
|
||||||
var p = parseMediaType(type);
|
|
||||||
var s = 0;
|
|
||||||
|
|
||||||
if (!p) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spec.type == p.type) {
|
|
||||||
s |= 4
|
|
||||||
} else if(spec.type != '*') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spec.subtype == p.subtype) {
|
|
||||||
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] == p.params[k];
|
|
||||||
})) {
|
|
||||||
s |= 1
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
q: spec.q,
|
|
||||||
s: s,
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function preferredMediaTypes(accept, provided) {
|
|
||||||
// RFC 2616 sec 14.2: no header = */*
|
|
||||||
accept = parseAccept(accept === undefined ? '*/*' : accept || '');
|
|
||||||
if (provided) {
|
|
||||||
return provided.map(function(type) {
|
|
||||||
return [type, getMediaTypePriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type) {
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.full;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
37
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/negotiator.js
generated
vendored
37
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/lib/negotiator.js
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
module.exports = Negotiator;
|
|
||||||
Negotiator.Negotiator = Negotiator;
|
|
||||||
|
|
||||||
function Negotiator(request) {
|
|
||||||
if (!(this instanceof Negotiator)) return new Negotiator(request);
|
|
||||||
this.request = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
var set = { charset: 'accept-charset',
|
|
||||||
encoding: 'accept-encoding',
|
|
||||||
language: 'accept-language',
|
|
||||||
mediaType: 'accept' };
|
|
||||||
|
|
||||||
|
|
||||||
function capitalize(string){
|
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(set).forEach(function (k) {
|
|
||||||
var header = set[k],
|
|
||||||
method = require('./'+k+'.js'),
|
|
||||||
singular = k,
|
|
||||||
plural = k + 's';
|
|
||||||
|
|
||||||
Negotiator.prototype[plural] = function (available) {
|
|
||||||
return method(this.request.headers[header], available);
|
|
||||||
};
|
|
||||||
|
|
||||||
Negotiator.prototype[singular] = function(available) {
|
|
||||||
var set = this[plural](available);
|
|
||||||
if (set) return set[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep preferred* methods for legacy compatibility
|
|
||||||
Negotiator.prototype['preferred'+capitalize(plural)] = Negotiator.prototype[plural];
|
|
||||||
Negotiator.prototype['preferred'+capitalize(singular)] = Negotiator.prototype[singular];
|
|
||||||
})
|
|
49
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/package.json
generated
vendored
49
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/package.json
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"name": "negotiator",
|
|
||||||
"description": "HTTP content negotiation",
|
|
||||||
"version": "0.4.7",
|
|
||||||
"author": {
|
|
||||||
"name": "Federico Romero",
|
|
||||||
"email": "federico.romero@outboxlabs.com"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/federomero/negotiator.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"content negotiation",
|
|
||||||
"accept",
|
|
||||||
"accept-language",
|
|
||||||
"accept-encoding",
|
|
||||||
"accept-charset"
|
|
||||||
],
|
|
||||||
"engine": "node >= 0.6",
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"nodeunit": "0.8.x"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "nodeunit test"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"main": "lib/negotiator.js",
|
|
||||||
"readme": "# Negotiator [![Build Status](https://travis-ci.org/federomero/negotiator.png)](https://travis-ci.org/federomero/negotiator)\n\nAn HTTP content negotiator for node.js written in javascript.\n\n# Accept Negotiation\n\n Negotiator = require('negotiator')\n\n availableMediaTypes = ['text/html', 'text/plain', 'application/json']\n\n // The negotiator constructor receives a request object\n negotiator = new Negotiator(request)\n\n // Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'\n\n negotiator.mediaTypes()\n // -> ['text/html', 'image/jpeg', 'application/*']\n\n negotiator.mediaTypes(availableMediaTypes)\n // -> ['text/html', 'application/json']\n\n negotiator.mediaType(availableMediaTypes)\n // -> 'text/html'\n\nYou can check a working example at `examples/accept.js`.\n\n## Methods\n\n`mediaTypes(availableMediaTypes)`:\n\nReturns an array of preferred media types ordered by priority from a list of available media types.\n\n`mediaType(availableMediaType)`:\n\nReturns the top preferred media type from a list of available media types.\n\n# Accept-Language Negotiation\n\n Negotiator = require('negotiator')\n\n negotiator = new Negotiator(request)\n\n availableLanguages = 'en', 'es', 'fr'\n\n // Let's say Accept-Language header is 'en;q=0.8, es, pt'\n\n negotiator.languages()\n // -> ['es', 'pt', 'en']\n\n negotiator.languages(availableLanguages)\n // -> ['es', 'en']\n\n language = negotiator.language(availableLanguages)\n // -> 'es'\n\nYou can check a working example at `examples/language.js`.\n\n## Methods\n\n`languages(availableLanguages)`:\n\nReturns an array of preferred languages ordered by priority from a list of available languages.\n\n`language(availableLanguages)`:\n\nReturns the top preferred language from a list of available languages.\n\n# Accept-Charset Negotiation\n\n Negotiator = require('negotiator')\n\n availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']\n\n negotiator = new Negotiator(request)\n\n // Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'\n\n negotiator.charsets()\n // -> ['utf-8', 'iso-8859-1', 'utf-7']\n\n negotiator.charsets(availableCharsets)\n // -> ['utf-8', 'iso-8859-1']\n\n negotiator.charset(availableCharsets)\n // -> 'utf-8'\n\nYou can check a working example at `examples/charset.js`.\n\n## Methods\n\n`charsets(availableCharsets)`:\n\nReturns an array of preferred charsets ordered by priority from a list of available charsets.\n\n`charset(availableCharsets)`:\n\nReturns the top preferred charset from a list of available charsets.\n\n# Accept-Encoding Negotiation\n\n Negotiator = require('negotiator').Negotiator\n\n availableEncodings = ['identity', 'gzip']\n\n negotiator = new Negotiator(request)\n\n // Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'\n\n negotiator.encodings()\n // -> ['gzip', 'identity', 'compress']\n\n negotiator.encodings(availableEncodings)\n // -> ['gzip', 'identity']\n\n negotiator.encoding(availableEncodings)\n // -> 'gzip'\n\nYou can check a working example at `examples/encoding.js`.\n\n## Methods\n\n`encodings(availableEncodings)`:\n\nReturns an array of preferred encodings ordered by priority from a list of available encodings.\n\n`encoding(availableEncodings)`:\n\nReturns the top preferred encoding from a list of available encodings.\n\n# License\n\nMIT\n",
|
|
||||||
"readmeFilename": "readme.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/federomero/negotiator/issues"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"_id": "negotiator@0.4.7",
|
|
||||||
"_from": "negotiator@0.4.7"
|
|
||||||
}
|
|
132
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/readme.md
generated
vendored
132
node_modules/errorhandler/node_modules/accepts/node_modules/negotiator/readme.md
generated
vendored
|
@ -1,132 +0,0 @@
|
||||||
# Negotiator [![Build Status](https://travis-ci.org/federomero/negotiator.png)](https://travis-ci.org/federomero/negotiator)
|
|
||||||
|
|
||||||
An HTTP content negotiator for node.js written in javascript.
|
|
||||||
|
|
||||||
# Accept Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator')
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`mediaTypes(availableMediaTypes)`:
|
|
||||||
|
|
||||||
Returns an array of preferred media types ordered by priority from a list of available media types.
|
|
||||||
|
|
||||||
`mediaType(availableMediaType)`:
|
|
||||||
|
|
||||||
Returns the top preferred media type from a list of available media types.
|
|
||||||
|
|
||||||
# Accept-Language Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator')
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`languages(availableLanguages)`:
|
|
||||||
|
|
||||||
Returns an array of preferred languages ordered by priority from a list of available languages.
|
|
||||||
|
|
||||||
`language(availableLanguages)`:
|
|
||||||
|
|
||||||
Returns the top preferred language from a list of available languages.
|
|
||||||
|
|
||||||
# Accept-Charset Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator')
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`charsets(availableCharsets)`:
|
|
||||||
|
|
||||||
Returns an array of preferred charsets ordered by priority from a list of available charsets.
|
|
||||||
|
|
||||||
`charset(availableCharsets)`:
|
|
||||||
|
|
||||||
Returns the top preferred charset from a list of available charsets.
|
|
||||||
|
|
||||||
# Accept-Encoding Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator').Negotiator
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`encodings(availableEncodings)`:
|
|
||||||
|
|
||||||
Returns an array of preferred encodings ordered by priority from a list of available encodings.
|
|
||||||
|
|
||||||
`encoding(availableEncodings)`:
|
|
||||||
|
|
||||||
Returns the top preferred encoding from a list of available encodings.
|
|
||||||
|
|
||||||
# License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"name": "accepts",
|
|
||||||
"description": "Higher-level content negotiation",
|
|
||||||
"version": "1.0.6",
|
|
||||||
"author": {
|
|
||||||
"name": "Jonathan Ong",
|
|
||||||
"email": "me@jongleberry.com",
|
|
||||||
"url": "http://jongleberry.com"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/expressjs/accepts"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"mime-types": "~1.0.0",
|
|
||||||
"negotiator": "0.4.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"istanbul": "0.2.11",
|
|
||||||
"mocha": "*",
|
|
||||||
"should": "*"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "mocha --require should --reporter dot test/",
|
|
||||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require should --reporter dot test/",
|
|
||||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require should --reporter spec test/"
|
|
||||||
},
|
|
||||||
"readme": "# Accepts\n\n[![NPM version](https://badge.fury.io/js/accepts.svg)](http://badge.fury.io/js/accepts)\n[![Build Status](https://travis-ci.org/expressjs/accepts.svg?branch=master)](https://travis-ci.org/expressjs/accepts)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/accepts.svg?branch=master)](https://coveralls.io/r/expressjs/accepts)\n\nHigher level content negotation based on [negotiator](https://github.com/federomero/negotiator). Extracted from [koa](https://github.com/koajs/koa) for general use.\n\nIn addition to negotatior, it allows:\n\n- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` as well as `('text/html', 'application/json')`.\n- Allows type shorthands such as `json`.\n- Returns `false` when no types match\n- Treats non-existent headers as `*`\n\n## API\n\n### var accept = new Accepts(req)\n\n```js\nvar accepts = require('accepts')\n\nhttp.createServer(function (req, res) {\n var accept = accepts(req)\n})\n```\n\n### accept\\[property\\]\\(\\)\n\nReturns all the explicitly accepted content property as an array in descending priority.\n\n- `accept.types()`\n- `accept.encodings()`\n- `accept.charsets()`\n- `accept.languages()`\n\nThey are also aliased in singular form such as `accept.type()`. `accept.languages()` is also aliased as `accept.langs()`, etc.\n\nNote: you should almost never do this in a real app as it defeats the purpose of content negotiation.\n\nExample:\n\n```js\n// in Google Chrome\nvar encodings = accept.encodings() // -> ['sdch', 'gzip', 'deflate']\n```\n\nSince you probably don't support `sdch`, you should just supply the encodings you support:\n\n```js\nvar encoding = accept.encodings('gzip', 'deflate') // -> 'gzip', probably\n```\n\n### accept\\[property\\]\\(values, ...\\)\n\nYou can either have `values` be an array or have an argument list of values.\n\nIf the client does not accept any `values`, `false` will be returned.\nIf the client accepts any `values`, the preferred `value` will be return.\n\nFor `accept.types()`, shorthand mime types are allowed.\n\nExample:\n\n```js\n// req.headers.accept = 'application/json'\n\naccept.types('json') // -> 'json'\naccept.types('html', 'json') // -> 'json'\naccept.types('html') // -> false\n\n// req.headers.accept = ''\n// which is equivalent to `*`\n\naccept.types() // -> [], no explicit types\naccept.types('text/html', 'text/json') // -> 'text/html', since it was first\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/expressjs/accepts/issues"
|
|
||||||
},
|
|
||||||
"_id": "accepts@1.0.6",
|
|
||||||
"_from": "accepts@~1.0.4"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
components
|
|
||||||
build
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
build: components index.js
|
|
||||||
@component build
|
|
||||||
|
|
||||||
components:
|
|
||||||
@Component install
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -fr build components template.js
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
|
@ -1,15 +0,0 @@
|
||||||
|
|
||||||
# escape-html
|
|
||||||
|
|
||||||
Escape HTML entities
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
var escape = require('escape-html');
|
|
||||||
escape(str);
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"name": "escape-html",
|
|
||||||
"description": "Escape HTML entities",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"keywords": ["escape", "html", "utility"],
|
|
||||||
"dependencies": {},
|
|
||||||
"scripts": [
|
|
||||||
"index.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
/**
|
|
||||||
* Escape special characters in the given string of html.
|
|
||||||
*
|
|
||||||
* @param {String} html
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = function(html) {
|
|
||||||
return String(html)
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/"/g, '"')
|
|
||||||
.replace(/'/g, ''')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>');
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"name": "escape-html",
|
|
||||||
"description": "Escape HTML entities",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"keywords": [
|
|
||||||
"escape",
|
|
||||||
"html",
|
|
||||||
"utility"
|
|
||||||
],
|
|
||||||
"dependencies": {},
|
|
||||||
"main": "index.js",
|
|
||||||
"component": {
|
|
||||||
"scripts": {
|
|
||||||
"escape-html/index.js": "index.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/component/escape-html.git"
|
|
||||||
},
|
|
||||||
"readme": "\n# escape-html\n\n Escape HTML entities\n\n## Example\n\n```js\nvar escape = require('escape-html');\nescape(str);\n```\n\n## License\n\n MIT",
|
|
||||||
"readmeFilename": "Readme.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/component/escape-html/issues"
|
|
||||||
},
|
|
||||||
"_id": "escape-html@1.0.1",
|
|
||||||
"_from": "escape-html@1.0.1"
|
|
||||||
}
|
|
|
@ -1,41 +1,43 @@
|
||||||
{
|
{
|
||||||
"name": "errorhandler",
|
"name": "errorhandler",
|
||||||
"description": "connect's default error handler page",
|
"description": "Development-only error handler middleware",
|
||||||
"version": "1.1.1",
|
"version": "1.5.1",
|
||||||
"author": {
|
"contributors": [
|
||||||
"name": "Jonathan Ong",
|
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||||
"email": "me@jongleberry.com",
|
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
|
||||||
"url": "http://jongleberry.com"
|
],
|
||||||
},
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": "expressjs/errorhandler",
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/expressjs/errorhandler"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.0.4",
|
"accepts": "~1.3.7",
|
||||||
"escape-html": "1.0.1"
|
"escape-html": "~1.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"connect": "3",
|
"after": "0.8.2",
|
||||||
"istanbul": "0.2.10",
|
"eslint": "5.16.0",
|
||||||
"mocha": "~1.20.1",
|
"eslint-config-standard": "12.0.0",
|
||||||
"should": "~4.0.1",
|
"eslint-plugin-import": "2.17.2",
|
||||||
"supertest": "~0.13.0"
|
"eslint-plugin-markdown": "1.0.0",
|
||||||
|
"eslint-plugin-node": "8.0.1",
|
||||||
|
"eslint-plugin-promise": "4.1.1",
|
||||||
|
"eslint-plugin-standard": "4.0.0",
|
||||||
|
"istanbul": "0.4.5",
|
||||||
|
"mocha": "6.1.4",
|
||||||
|
"supertest": "4.0.2"
|
||||||
},
|
},
|
||||||
|
"files": [
|
||||||
|
"public/",
|
||||||
|
"LICENSE",
|
||||||
|
"HISTORY.md",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha --reporter dot test/",
|
"lint": "eslint --plugin markdown --ext js,md .",
|
||||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/",
|
"test": "mocha --reporter spec --bail --check-leaks test/",
|
||||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec 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/"
|
||||||
"readme": "# errorhandler\n\n[![NPM version](https://badge.fury.io/js/errorhandler.svg)](http://badge.fury.io/js/errorhandler)\n[![Build Status](https://travis-ci.org/expressjs/errorhandler.svg?branch=master)](https://travis-ci.org/expressjs/errorhandler)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/errorhandler.svg?branch=master)](https://coveralls.io/r/expressjs/errorhandler)\n\nPreviously `connect.errorHandler()`.\n\n## Install\n\n```sh\n$ npm install errorhandler\n```\n\n## API\n\n### errorhandler()\n\nCreate new middleware to handle errors and respond with content negotiation.\nThis middleware is only intended to be used in a development environment, as\nthe full error stack traces will be send back to the client when an error\noccurs.\n\n## Example\n\n```js\nvar connect = require('connect')\nvar errorhandler = require('errorhandler')\n\nvar app = connect()\n\nif (process.env.NODE_ENV === 'development') {\n app.use(errorhandler())\n}\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n",
|
}
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/expressjs/errorhandler/issues"
|
|
||||||
},
|
|
||||||
"_id": "errorhandler@1.1.1",
|
|
||||||
"_from": "errorhandler@"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
.git*
|
|
||||||
benchmarks/
|
|
||||||
coverage/
|
|
||||||
docs/
|
|
||||||
examples/
|
|
||||||
support/
|
|
||||||
test/
|
|
||||||
testing.js
|
|
||||||
.DS_Store
|
|
||||||
.travis.yml
|
|
||||||
Contributing.md
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,8 @@
|
||||||
(The MIT License)
|
(The MIT License)
|
||||||
|
|
||||||
Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
|
Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
|
||||||
|
Copyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com>
|
||||||
|
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,113 +1,260 @@
|
||||||
[![express logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)
|
[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)
|
||||||
|
|
||||||
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
|
**Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org).**
|
||||||
|
|
||||||
|
**This project has a [Code of Conduct][].**
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
* [Installation](#Installation)
|
||||||
|
* [Features](#Features)
|
||||||
|
* [Docs & Community](#docs--community)
|
||||||
|
* [Quick Start](#Quick-Start)
|
||||||
|
* [Running Tests](#Running-Tests)
|
||||||
|
* [Philosophy](#Philosophy)
|
||||||
|
* [Examples](#Examples)
|
||||||
|
* [Contributing to Express](#Contributing)
|
||||||
|
* [TC (Technical Committee)](#tc-technical-committee)
|
||||||
|
* [Triagers](#triagers)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
|
||||||
|
[![NPM Version][npm-version-image]][npm-url]
|
||||||
|
[![NPM Install Size][npm-install-size-image]][npm-install-size-url]
|
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-downloads-url]
|
||||||
|
[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]
|
||||||
|
|
||||||
[![NPM version](https://badge.fury.io/js/express.svg)](http://badge.fury.io/js/express)
|
|
||||||
[![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express)
|
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/visionmedia/express.svg)](https://coveralls.io/r/visionmedia/express)
|
|
||||||
[![Gittip](http://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/)
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
var express = require('express');
|
const express = require('express')
|
||||||
var app = express();
|
const app = express()
|
||||||
|
|
||||||
app.get('/', function(req, res){
|
app.get('/', function (req, res) {
|
||||||
res.send('Hello World');
|
res.send('Hello World')
|
||||||
});
|
})
|
||||||
|
|
||||||
app.listen(3000);
|
app.listen(3000)
|
||||||
```
|
```
|
||||||
|
|
||||||
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x).
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
$ npm install express
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/).
|
||||||
|
|
||||||
## Quick Start
|
Before installing, [download and install Node.js](https://nodejs.org/en/download/).
|
||||||
|
Node.js 0.10 or higher is required.
|
||||||
|
|
||||||
The quickest way to get started with express is to utilize the executable [`express(1)`](http://github.com/expressjs/generator) to generate an application as shown below:
|
If this is a brand new project, make sure to create a `package.json` first with
|
||||||
|
the [`npm init` command](https://docs.npmjs.com/creating-a-package-json-file).
|
||||||
|
|
||||||
Install the executable. The executable's major version will match Express's:
|
Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
$ npm install -g express-generator@3
|
```console
|
||||||
|
$ npm install express
|
||||||
|
```
|
||||||
|
|
||||||
Create the app:
|
Follow [our installing guide](http://expressjs.com/en/starter/installing.html)
|
||||||
|
for more information.
|
||||||
$ express /tmp/foo && cd /tmp/foo
|
|
||||||
|
|
||||||
Install dependencies:
|
|
||||||
|
|
||||||
$ npm install
|
|
||||||
|
|
||||||
Start the server:
|
|
||||||
|
|
||||||
$ npm start
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Robust routing
|
* Robust routing
|
||||||
|
* Focus on high performance
|
||||||
|
* Super-high test coverage
|
||||||
* HTTP helpers (redirection, caching, etc)
|
* HTTP helpers (redirection, caching, etc)
|
||||||
* View system supporting 14+ template engines
|
* View system supporting 14+ template engines
|
||||||
* Content negotiation
|
* Content negotiation
|
||||||
* Focus on high performance
|
|
||||||
* Executable for generating applications quickly
|
* Executable for generating applications quickly
|
||||||
* High test coverage
|
|
||||||
|
## Docs & Community
|
||||||
|
|
||||||
|
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
|
||||||
|
* [#express](https://web.libera.chat/#express) on [Libera Chat](https://libera.chat) IRC
|
||||||
|
* [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
|
||||||
|
* Visit the [Wiki](https://github.com/expressjs/express/wiki)
|
||||||
|
* [Google Group](https://groups.google.com/group/express-js) for discussion
|
||||||
|
* [Gitter](https://gitter.im/expressjs/express) for support and discussion
|
||||||
|
|
||||||
|
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:
|
||||||
|
|
||||||
|
Install the executable. The executable's major version will match Express's:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ npm install -g express-generator@4
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the app:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ express /tmp/foo && cd /tmp/foo
|
||||||
|
```
|
||||||
|
|
||||||
|
Install dependencies:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Start the server:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
View the website at: http://localhost:3000
|
||||||
|
|
||||||
## Philosophy
|
## Philosophy
|
||||||
|
|
||||||
The Express philosophy is to provide small, robust tooling for HTTP servers, making
|
The Express philosophy is to provide small, robust tooling for HTTP servers, making
|
||||||
it a great solution for single page applications, web sites, hybrids, or public
|
it a great solution for single page applications, websites, hybrids, or public
|
||||||
HTTP APIs.
|
HTTP APIs.
|
||||||
|
|
||||||
Express does not force you to use any specific ORM or template engine. With support for over
|
Express does not force you to use any specific ORM or template engine. With support for over
|
||||||
14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js),
|
14 template engines via [Consolidate.js](https://github.com/tj/consolidate.js),
|
||||||
you can quickly craft your perfect framework.
|
you can quickly craft your perfect framework.
|
||||||
|
|
||||||
## More Information
|
## Examples
|
||||||
|
|
||||||
* [Website and Documentation](http://expressjs.com/) stored at [visionmedia/expressjs.com](https://github.com/visionmedia/expressjs.com)
|
To view the examples, clone the Express repo and install the dependencies:
|
||||||
* Join #express on freenode
|
|
||||||
* [Google Group](http://groups.google.com/group/express-js) for discussion
|
|
||||||
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) and [defunctzombie](https://twitter.com/defunctzombie) on twitter for updates
|
|
||||||
* Visit the [Wiki](http://github.com/visionmedia/express/wiki)
|
|
||||||
* [Русскоязычная документация](http://jsman.ru/express/)
|
|
||||||
* Run express examples [online](https://runnable.com/express)
|
|
||||||
|
|
||||||
## Viewing Examples
|
```console
|
||||||
|
$ git clone https://github.com/expressjs/express.git --depth 1
|
||||||
|
$ cd express
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
Clone the Express repo, then install the dev dependencies to install all the example / test suite dependencies:
|
Then run whichever example you want:
|
||||||
|
|
||||||
$ git clone git://github.com/visionmedia/express.git --depth 1
|
```console
|
||||||
$ cd express
|
$ node examples/content-negotiation
|
||||||
$ npm install
|
```
|
||||||
|
|
||||||
Then run whichever tests you want:
|
## Contributing
|
||||||
|
|
||||||
$ node examples/content-negotiation
|
[![Linux Build][github-actions-ci-image]][github-actions-ci-url]
|
||||||
|
[![Windows Build][appveyor-image]][appveyor-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
You can also view live examples here:
|
The Express.js project welcomes all constructive contributions. Contributions take many forms,
|
||||||
|
from code for bug fixes and enhancements, to additions and fixes to documentation, additional
|
||||||
|
tests, triaging incoming pull requests and issues, and more!
|
||||||
|
|
||||||
<a href="https://runnable.com/express" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a>
|
See the [Contributing Guide](Contributing.md) for more technical details on contributing.
|
||||||
|
|
||||||
## Running Tests
|
### Security Issues
|
||||||
|
|
||||||
To run the test suite, first invoke the following command within the repo, installing the development dependencies:
|
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
|
||||||
|
|
||||||
$ npm install
|
### Running Tests
|
||||||
|
|
||||||
Then run the tests:
|
To run the test suite, first install the dependencies, then run `npm test`:
|
||||||
|
|
||||||
```sh
|
```console
|
||||||
|
$ npm install
|
||||||
$ npm test
|
$ npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributors
|
## People
|
||||||
|
|
||||||
|
The original author of Express is [TJ Holowaychuk](https://github.com/tj)
|
||||||
|
|
||||||
|
[List of all contributors](https://github.com/expressjs/express/graphs/contributors)
|
||||||
|
|
||||||
|
### TC (Technical Committee)
|
||||||
|
|
||||||
|
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
|
||||||
|
* [jonchurch](https://github.com/jonchurch) - **Jon Church**
|
||||||
|
* [wesleytodd](https://github.com/wesleytodd) - **Wes Todd**
|
||||||
|
* [LinusU](https://github.com/LinusU) - **Linus Unnebäck**
|
||||||
|
* [blakeembrey](https://github.com/blakeembrey) - **Blake Embrey**
|
||||||
|
* [sheplu](https://github.com/sheplu) - **Jean Burellier**
|
||||||
|
* [crandmck](https://github.com/crandmck) - **Rand McKinney**
|
||||||
|
* [ctcpip](https://github.com/ctcpip) - **Chris de Almeida**
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>TC emeriti members</summary>
|
||||||
|
|
||||||
|
#### TC emeriti members
|
||||||
|
|
||||||
|
* [dougwilson](https://github.com/dougwilson) - **Douglas Wilson**
|
||||||
|
* [hacksparrow](https://github.com/hacksparrow) - **Hage Yaapa**
|
||||||
|
* [jonathanong](https://github.com/jonathanong) - **jongleberry**
|
||||||
|
* [niftylettuce](https://github.com/niftylettuce) - **niftylettuce**
|
||||||
|
* [troygoode](https://github.com/troygoode) - **Troy Goode**
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
### Triagers
|
||||||
|
|
||||||
|
* [aravindvnair99](https://github.com/aravindvnair99) - **Aravind Nair**
|
||||||
|
* [carpasse](https://github.com/carpasse) - **Carlos Serrano**
|
||||||
|
* [CBID2](https://github.com/CBID2) - **Christine Belzie**
|
||||||
|
* [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim**
|
||||||
|
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
|
||||||
|
* [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin**
|
||||||
|
* [0ss](https://github.com/0ss) - **Salah**
|
||||||
|
* [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him)
|
||||||
|
* [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
|
||||||
|
* [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him)
|
||||||
|
* [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego**
|
||||||
|
* [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him)
|
||||||
|
* [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Triagers emeriti members</summary>
|
||||||
|
|
||||||
|
#### Emeritus Triagers
|
||||||
|
|
||||||
|
* [AuggieH](https://github.com/AuggieH) - **Auggie Hudak**
|
||||||
|
* [G-Rath](https://github.com/G-Rath) - **Gareth Jones**
|
||||||
|
* [MohammadXroid](https://github.com/MohammadXroid) - **Mohammad Ayashi**
|
||||||
|
* [NawafSwe](https://github.com/NawafSwe) - **Nawaf Alsharqi**
|
||||||
|
* [NotMoni](https://github.com/NotMoni) - **Moni**
|
||||||
|
* [VigneshMurugan](https://github.com/VigneshMurugan) - **Vignesh Murugan**
|
||||||
|
* [davidmashe](https://github.com/davidmashe) - **David Ashe**
|
||||||
|
* [digitaIfabric](https://github.com/digitaIfabric) - **David**
|
||||||
|
* [e-l-i-s-e](https://github.com/e-l-i-s-e) - **Elise Bonner**
|
||||||
|
* [fed135](https://github.com/fed135) - **Frederic Charette**
|
||||||
|
* [firmanJS](https://github.com/firmanJS) - **Firman Abdul Hakim**
|
||||||
|
* [getspooky](https://github.com/getspooky) - **Yasser Ameur**
|
||||||
|
* [ghinks](https://github.com/ghinks) - **Glenn**
|
||||||
|
* [ghousemohamed](https://github.com/ghousemohamed) - **Ghouse Mohamed**
|
||||||
|
* [gireeshpunathil](https://github.com/gireeshpunathil) - **Gireesh Punathil**
|
||||||
|
* [jake32321](https://github.com/jake32321) - **Jake Reed**
|
||||||
|
* [jonchurch](https://github.com/jonchurch) - **Jon Church**
|
||||||
|
* [lekanikotun](https://github.com/lekanikotun) - **Troy Goode**
|
||||||
|
* [marsonya](https://github.com/marsonya) - **Lekan Ikotun**
|
||||||
|
* [mastermatt](https://github.com/mastermatt) - **Matt R. Wilson**
|
||||||
|
* [maxakuru](https://github.com/maxakuru) - **Max Edell**
|
||||||
|
* [mlrawlings](https://github.com/mlrawlings) - **Michael Rawlings**
|
||||||
|
* [rodion-arr](https://github.com/rodion-arr) - **Rodion Abdurakhimov**
|
||||||
|
* [sheplu](https://github.com/sheplu) - **Jean Burellier**
|
||||||
|
* [tarunyadav1](https://github.com/tarunyadav1) - **Tarun yadav**
|
||||||
|
* [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe**
|
||||||
|
</details>
|
||||||
|
|
||||||
Author: [TJ Holowaychuk](http://github.com/visionmedia)
|
|
||||||
Lead Maintainer: [Roman Shtylman](https://github.com/defunctzombie)
|
|
||||||
Contributors: https://github.com/visionmedia/express/graphs/contributors
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/express/master?label=windows
|
||||||
|
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
|
||||||
|
[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=linux
|
||||||
|
[github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml
|
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/express
|
||||||
|
[npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true
|
||||||
|
[npm-install-size-image]: https://badgen.net/packagephobia/install/express
|
||||||
|
[npm-install-size-url]: https://packagephobia.com/result?p=express
|
||||||
|
[npm-url]: https://npmjs.org/package/express
|
||||||
|
[npm-version-image]: https://badgen.net/npm/v/express
|
||||||
|
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge
|
||||||
|
[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express
|
||||||
|
[Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md
|
||||||
|
|
|
@ -1,2 +1,11 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
module.exports = require('./lib/express');
|
module.exports = require('./lib/express');
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
/**
|
/*!
|
||||||
* Module dependencies.
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var mixin = require('utils-merge');
|
'use strict';
|
||||||
var escapeHtml = require('escape-html');
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var finalhandler = require('finalhandler');
|
||||||
var Router = require('./router');
|
var Router = require('./router');
|
||||||
var methods = require('methods');
|
var methods = require('methods');
|
||||||
var middleware = require('./middleware/init');
|
var middleware = require('./middleware/init');
|
||||||
|
@ -12,9 +22,21 @@ var debug = require('debug')('express:application');
|
||||||
var View = require('./view');
|
var View = require('./view');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var compileETag = require('./utils').compileETag;
|
var compileETag = require('./utils').compileETag;
|
||||||
|
var compileQueryParser = require('./utils').compileQueryParser;
|
||||||
var compileTrust = require('./utils').compileTrust;
|
var compileTrust = require('./utils').compileTrust;
|
||||||
var deprecate = require('./utils').deprecate;
|
var deprecate = require('depd')('express');
|
||||||
|
var flatten = require('array-flatten');
|
||||||
|
var merge = require('utils-merge');
|
||||||
var resolve = require('path').resolve;
|
var resolve = require('path').resolve;
|
||||||
|
var setPrototypeOf = require('setprototypeof')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var hasOwnProperty = Object.prototype.hasOwnProperty
|
||||||
|
var slice = Array.prototype.slice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application prototype.
|
* Application prototype.
|
||||||
|
@ -22,6 +44,13 @@ var resolve = require('path').resolve;
|
||||||
|
|
||||||
var app = exports = module.exports = {};
|
var app = exports = module.exports = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variable for trust proxy inheritance back-compat
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the server.
|
* Initialize the server.
|
||||||
*
|
*
|
||||||
|
@ -29,39 +58,54 @@ var app = exports = module.exports = {};
|
||||||
* - setup default middleware
|
* - setup default middleware
|
||||||
* - setup route reflection methods
|
* - setup route reflection methods
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.init = function(){
|
app.init = function init() {
|
||||||
this.cache = {};
|
this.cache = {};
|
||||||
this.settings = {};
|
|
||||||
this.engines = {};
|
this.engines = {};
|
||||||
|
this.settings = {};
|
||||||
|
|
||||||
this.defaultConfiguration();
|
this.defaultConfiguration();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize application configuration.
|
* Initialize application configuration.
|
||||||
*
|
* @private
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.defaultConfiguration = function(){
|
app.defaultConfiguration = function defaultConfiguration() {
|
||||||
|
var env = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
// default settings
|
// default settings
|
||||||
this.enable('x-powered-by');
|
this.enable('x-powered-by');
|
||||||
this.set('etag', 'weak');
|
this.set('etag', 'weak');
|
||||||
var env = process.env.NODE_ENV || 'development';
|
|
||||||
this.set('env', env);
|
this.set('env', env);
|
||||||
|
this.set('query parser', 'extended');
|
||||||
this.set('subdomain offset', 2);
|
this.set('subdomain offset', 2);
|
||||||
this.set('trust proxy', false);
|
this.set('trust proxy', false);
|
||||||
|
|
||||||
|
// trust proxy inherit back-compat
|
||||||
|
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
|
||||||
|
configurable: true,
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
|
||||||
debug('booting in %s mode', env);
|
debug('booting in %s mode', env);
|
||||||
|
|
||||||
// inherit protos
|
this.on('mount', function onmount(parent) {
|
||||||
this.on('mount', function(parent){
|
// inherit trust proxy
|
||||||
this.request.__proto__ = parent.request;
|
if (this.settings[trustProxyDefaultSymbol] === true
|
||||||
this.response.__proto__ = parent.response;
|
&& typeof parent.settings['trust proxy fn'] === 'function') {
|
||||||
this.engines.__proto__ = parent.engines;
|
delete this.settings['trust proxy'];
|
||||||
this.settings.__proto__ = parent.settings;
|
delete this.settings['trust proxy fn'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// inherit protos
|
||||||
|
setPrototypeOf(this.request, parent.request)
|
||||||
|
setPrototypeOf(this.response, parent.response)
|
||||||
|
setPrototypeOf(this.engines, parent.engines)
|
||||||
|
setPrototypeOf(this.settings, parent.settings)
|
||||||
});
|
});
|
||||||
|
|
||||||
// setup locals
|
// setup locals
|
||||||
|
@ -95,16 +139,16 @@ app.defaultConfiguration = function(){
|
||||||
* We cannot add the base router in the defaultConfiguration because
|
* We cannot add the base router in the defaultConfiguration because
|
||||||
* it reads app settings which might be set after that has run.
|
* it reads app settings which might be set after that has run.
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
app.lazyrouter = function() {
|
app.lazyrouter = function lazyrouter() {
|
||||||
if (!this._router) {
|
if (!this._router) {
|
||||||
this._router = new Router({
|
this._router = new Router({
|
||||||
caseSensitive: this.enabled('case sensitive routing'),
|
caseSensitive: this.enabled('case sensitive routing'),
|
||||||
strict: this.enabled('strict routing')
|
strict: this.enabled('strict routing')
|
||||||
});
|
});
|
||||||
|
|
||||||
this._router.use(query());
|
this._router.use(query(this.get('query parser fn')));
|
||||||
this._router.use(middleware.init(this));
|
this._router.use(middleware.init(this));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -112,52 +156,29 @@ app.lazyrouter = function() {
|
||||||
/**
|
/**
|
||||||
* Dispatch a req, res pair into the application. Starts pipeline processing.
|
* Dispatch a req, res pair into the application. Starts pipeline processing.
|
||||||
*
|
*
|
||||||
* If no _done_ callback is provided, then default error handlers will respond
|
* If no callback is provided, then default error handlers will respond
|
||||||
* in the event of an error bubbling through the stack.
|
* in the event of an error bubbling through the stack.
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.handle = function(req, res, done) {
|
app.handle = function handle(req, res, callback) {
|
||||||
var env = this.get('env');
|
var router = this._router;
|
||||||
|
|
||||||
this._router.handle(req, res, function(err) {
|
// final handler
|
||||||
if (done) {
|
var done = callback || finalhandler(req, res, {
|
||||||
return done(err);
|
env: this.get('env'),
|
||||||
}
|
onerror: logerror.bind(this)
|
||||||
|
|
||||||
// unhandled error
|
|
||||||
if (err) {
|
|
||||||
// default to 500
|
|
||||||
if (res.statusCode < 400) res.statusCode = 500;
|
|
||||||
debug('default %s', res.statusCode);
|
|
||||||
|
|
||||||
// respect err.status
|
|
||||||
if (err.status) res.statusCode = err.status;
|
|
||||||
|
|
||||||
// production gets a basic error message
|
|
||||||
var msg = 'production' == env
|
|
||||||
? http.STATUS_CODES[res.statusCode]
|
|
||||||
: err.stack || err.toString();
|
|
||||||
msg = escapeHtml(msg);
|
|
||||||
|
|
||||||
// log to stderr in a non-test env
|
|
||||||
if ('test' != env) console.error(err.stack || err.toString());
|
|
||||||
if (res.headersSent) return req.socket.destroy();
|
|
||||||
res.setHeader('Content-Type', 'text/html');
|
|
||||||
res.setHeader('Content-Length', Buffer.byteLength(msg));
|
|
||||||
if ('HEAD' == req.method) return res.end();
|
|
||||||
res.end(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 404
|
|
||||||
debug('default 404');
|
|
||||||
res.statusCode = 404;
|
|
||||||
res.setHeader('Content-Type', 'text/html');
|
|
||||||
if ('HEAD' == req.method) return res.end();
|
|
||||||
res.end('Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl) + '\n');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// no routes
|
||||||
|
if (!router) {
|
||||||
|
debug('no routes defined on app');
|
||||||
|
done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
router.handle(req, res, done);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,40 +188,62 @@ app.handle = function(req, res, done) {
|
||||||
* If the _fn_ parameter is an express app, then it will be
|
* If the _fn_ parameter is an express app, then it will be
|
||||||
* mounted at the _route_ specified.
|
* mounted at the _route_ specified.
|
||||||
*
|
*
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.use = function(route, fn){
|
app.use = function use(fn) {
|
||||||
var mount_app;
|
var offset = 0;
|
||||||
|
var path = '/';
|
||||||
|
|
||||||
// default route to '/'
|
// default path to '/'
|
||||||
if ('string' != typeof route) fn = route, route = '/';
|
// disambiguate app.use([fn])
|
||||||
|
if (typeof fn !== 'function') {
|
||||||
|
var arg = fn;
|
||||||
|
|
||||||
// express app
|
while (Array.isArray(arg) && arg.length !== 0) {
|
||||||
if (fn.handle && fn.set) mount_app = fn;
|
arg = arg[0];
|
||||||
|
}
|
||||||
|
|
||||||
// restore .app property on req and res
|
// first arg is the path
|
||||||
if (mount_app) {
|
if (typeof arg !== 'function') {
|
||||||
debug('.use app under %s', route);
|
offset = 1;
|
||||||
mount_app.mountpath = route;
|
path = fn;
|
||||||
fn = function(req, res, next) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fns = flatten(slice.call(arguments, offset));
|
||||||
|
|
||||||
|
if (fns.length === 0) {
|
||||||
|
throw new TypeError('app.use() requires a middleware function')
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup router
|
||||||
|
this.lazyrouter();
|
||||||
|
var router = this._router;
|
||||||
|
|
||||||
|
fns.forEach(function (fn) {
|
||||||
|
// non-express app
|
||||||
|
if (!fn || !fn.handle || !fn.set) {
|
||||||
|
return router.use(path, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug('.use app under %s', path);
|
||||||
|
fn.mountpath = path;
|
||||||
|
fn.parent = this;
|
||||||
|
|
||||||
|
// restore .app property on req and res
|
||||||
|
router.use(path, function mounted_app(req, res, next) {
|
||||||
var orig = req.app;
|
var orig = req.app;
|
||||||
mount_app.handle(req, res, function(err) {
|
fn.handle(req, res, function (err) {
|
||||||
req.__proto__ = orig.request;
|
setPrototypeOf(req, orig.request)
|
||||||
res.__proto__ = orig.response;
|
setPrototypeOf(res, orig.response)
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
this.lazyrouter();
|
// mounted an app
|
||||||
this._router.use(route, fn);
|
fn.emit('mount', this);
|
||||||
|
}, this);
|
||||||
// mounted an app
|
|
||||||
if (mount_app) {
|
|
||||||
mount_app.parent = this;
|
|
||||||
mount_app.emit('mount', this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
@ -212,10 +255,10 @@ app.use = function(route, fn){
|
||||||
* Routes are isolated middleware stacks for specific paths.
|
* Routes are isolated middleware stacks for specific paths.
|
||||||
* See the Route api docs for details.
|
* See the Route api docs for details.
|
||||||
*
|
*
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.route = function(path){
|
app.route = function route(path) {
|
||||||
this.lazyrouter();
|
this.lazyrouter();
|
||||||
return this._router.route(path);
|
return this._router.route(path);
|
||||||
};
|
};
|
||||||
|
@ -226,9 +269,9 @@ app.route = function(path){
|
||||||
*
|
*
|
||||||
* By default will `require()` the engine based on the
|
* By default will `require()` the engine based on the
|
||||||
* file extension. For example if you try to render
|
* file extension. For example if you try to render
|
||||||
* a "foo.jade" file Express will invoke the following internally:
|
* a "foo.ejs" file Express will invoke the following internally:
|
||||||
*
|
*
|
||||||
* app.engine('jade', require('jade').__express);
|
* app.engine('ejs', require('ejs').__express);
|
||||||
*
|
*
|
||||||
* For engines that do not provide `.__express` out of the box,
|
* For engines that do not provide `.__express` out of the box,
|
||||||
* or if you wish to "map" a different extension to the template engine
|
* or if you wish to "map" a different extension to the template engine
|
||||||
|
@ -240,10 +283,10 @@ app.route = function(path){
|
||||||
* In this case EJS provides a `.renderFile()` method with
|
* In this case EJS provides a `.renderFile()` method with
|
||||||
* the same signature that Express expects: `(path, options, callback)`,
|
* the same signature that Express expects: `(path, options, callback)`,
|
||||||
* though note that it aliases this method as `ejs.__express` internally
|
* though note that it aliases this method as `ejs.__express` internally
|
||||||
* so if you're using ".ejs" extensions you dont need to do anything.
|
* so if you're using ".ejs" extensions you don't need to do anything.
|
||||||
*
|
*
|
||||||
* Some template engines do not follow this convention, the
|
* Some template engines do not follow this convention, the
|
||||||
* [Consolidate.js](https://github.com/visionmedia/consolidate.js)
|
* [Consolidate.js](https://github.com/tj/consolidate.js)
|
||||||
* library was created to map all of node's popular template
|
* library was created to map all of node's popular template
|
||||||
* engines to follow this convention, thus allowing them to
|
* engines to follow this convention, thus allowing them to
|
||||||
* work seamlessly within Express.
|
* work seamlessly within Express.
|
||||||
|
@ -251,13 +294,22 @@ app.route = function(path){
|
||||||
* @param {String} ext
|
* @param {String} ext
|
||||||
* @param {Function} fn
|
* @param {Function} fn
|
||||||
* @return {app} for chaining
|
* @return {app} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.engine = function(ext, fn){
|
app.engine = function engine(ext, fn) {
|
||||||
if ('function' != typeof fn) throw new Error('callback function required');
|
if (typeof fn !== 'function') {
|
||||||
if ('.' != ext[0]) ext = '.' + ext;
|
throw new Error('callback function required');
|
||||||
this.engines[ext] = fn;
|
}
|
||||||
|
|
||||||
|
// get file extension
|
||||||
|
var extension = ext[0] !== '.'
|
||||||
|
? '.' + ext
|
||||||
|
: ext;
|
||||||
|
|
||||||
|
// store engine
|
||||||
|
this.engines[extension] = fn;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -270,21 +322,22 @@ app.engine = function(ext, fn){
|
||||||
* @param {String|Array} name
|
* @param {String|Array} name
|
||||||
* @param {Function} fn
|
* @param {Function} fn
|
||||||
* @return {app} for chaining
|
* @return {app} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.param = function(name, fn){
|
app.param = function param(name, fn) {
|
||||||
var self = this;
|
this.lazyrouter();
|
||||||
self.lazyrouter();
|
|
||||||
|
|
||||||
if (Array.isArray(name)) {
|
if (Array.isArray(name)) {
|
||||||
name.forEach(function(key) {
|
for (var i = 0; i < name.length; i++) {
|
||||||
self.param(key, fn);
|
this.param(name[i], fn);
|
||||||
});
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
self._router.param(name, fn);
|
this._router.param(name, fn);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -292,7 +345,7 @@ app.param = function(name, fn){
|
||||||
* Assign `setting` to `val`, or return `setting`'s value.
|
* Assign `setting` to `val`, or return `setting`'s value.
|
||||||
*
|
*
|
||||||
* app.set('foo', 'bar');
|
* app.set('foo', 'bar');
|
||||||
* app.get('foo');
|
* app.set('foo');
|
||||||
* // => "bar"
|
* // => "bar"
|
||||||
*
|
*
|
||||||
* Mounted servers inherit their parent server's settings.
|
* Mounted servers inherit their parent server's settings.
|
||||||
|
@ -300,27 +353,47 @@ app.param = function(name, fn){
|
||||||
* @param {String} setting
|
* @param {String} setting
|
||||||
* @param {*} [val]
|
* @param {*} [val]
|
||||||
* @return {Server} for chaining
|
* @return {Server} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.set = function(setting, val){
|
app.set = function set(setting, val) {
|
||||||
if (arguments.length === 1) {
|
if (arguments.length === 1) {
|
||||||
// app.get(setting)
|
// app.get(setting)
|
||||||
return this.settings[setting];
|
var settings = this.settings
|
||||||
|
|
||||||
|
while (settings && settings !== Object.prototype) {
|
||||||
|
if (hasOwnProperty.call(settings, setting)) {
|
||||||
|
return settings[setting]
|
||||||
|
}
|
||||||
|
|
||||||
|
settings = Object.getPrototypeOf(settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug('set "%s" to %o', setting, val);
|
||||||
|
|
||||||
// set value
|
// set value
|
||||||
this.settings[setting] = val;
|
this.settings[setting] = val;
|
||||||
|
|
||||||
// trigger matched settings
|
// trigger matched settings
|
||||||
switch (setting) {
|
switch (setting) {
|
||||||
case 'etag':
|
case 'etag':
|
||||||
debug('compile etag %s', val);
|
|
||||||
this.set('etag fn', compileETag(val));
|
this.set('etag fn', compileETag(val));
|
||||||
break;
|
break;
|
||||||
|
case 'query parser':
|
||||||
|
this.set('query parser fn', compileQueryParser(val));
|
||||||
|
break;
|
||||||
case 'trust proxy':
|
case 'trust proxy':
|
||||||
debug('compile trust proxy %s', val);
|
|
||||||
this.set('trust proxy fn', compileTrust(val));
|
this.set('trust proxy fn', compileTrust(val));
|
||||||
|
|
||||||
|
// trust proxy inherit back-compat
|
||||||
|
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
|
||||||
|
configurable: true,
|
||||||
|
value: false
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,10 +411,10 @@ app.set = function(setting, val){
|
||||||
* return value would be "/blog/admin".
|
* return value would be "/blog/admin".
|
||||||
*
|
*
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.path = function(){
|
app.path = function path() {
|
||||||
return this.parent
|
return this.parent
|
||||||
? this.parent.path() + this.mountpath
|
? this.parent.path() + this.mountpath
|
||||||
: '';
|
: '';
|
||||||
|
@ -359,11 +432,11 @@ app.path = function(){
|
||||||
*
|
*
|
||||||
* @param {String} setting
|
* @param {String} setting
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.enabled = function(setting){
|
app.enabled = function enabled(setting) {
|
||||||
return !!this.set(setting);
|
return Boolean(this.set(setting));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -378,10 +451,10 @@ app.enabled = function(setting){
|
||||||
*
|
*
|
||||||
* @param {String} setting
|
* @param {String} setting
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.disabled = function(setting){
|
app.disabled = function disabled(setting) {
|
||||||
return !this.set(setting);
|
return !this.set(setting);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -390,10 +463,10 @@ app.disabled = function(setting){
|
||||||
*
|
*
|
||||||
* @param {String} setting
|
* @param {String} setting
|
||||||
* @return {app} for chaining
|
* @return {app} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.enable = function(setting){
|
app.enable = function enable(setting) {
|
||||||
return this.set(setting, true);
|
return this.set(setting, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -402,10 +475,10 @@ app.enable = function(setting){
|
||||||
*
|
*
|
||||||
* @param {String} setting
|
* @param {String} setting
|
||||||
* @return {app} for chaining
|
* @return {app} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.disable = function(setting){
|
app.disable = function disable(setting) {
|
||||||
return this.set(setting, false);
|
return this.set(setting, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,12 +488,15 @@ app.disable = function(setting){
|
||||||
|
|
||||||
methods.forEach(function(method){
|
methods.forEach(function(method){
|
||||||
app[method] = function(path){
|
app[method] = function(path){
|
||||||
if ('get' == method && 1 == arguments.length) return this.set(path);
|
if (method === 'get' && arguments.length === 1) {
|
||||||
|
// app.get(setting)
|
||||||
|
return this.set(path);
|
||||||
|
}
|
||||||
|
|
||||||
this.lazyrouter();
|
this.lazyrouter();
|
||||||
|
|
||||||
var route = this._router.route(path);
|
var route = this._router.route(path);
|
||||||
route[method].apply(route, [].slice.call(arguments, 1));
|
route[method].apply(route, slice.call(arguments, 1));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -432,24 +508,25 @@ methods.forEach(function(method){
|
||||||
* @param {String} path
|
* @param {String} path
|
||||||
* @param {Function} ...
|
* @param {Function} ...
|
||||||
* @return {app} for chaining
|
* @return {app} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.all = function(path){
|
app.all = function all(path) {
|
||||||
this.lazyrouter();
|
this.lazyrouter();
|
||||||
|
|
||||||
var route = this._router.route(path);
|
var route = this._router.route(path);
|
||||||
var args = [].slice.call(arguments, 1);
|
var args = slice.call(arguments, 1);
|
||||||
methods.forEach(function(method){
|
|
||||||
route[method].apply(route, args);
|
for (var i = 0; i < methods.length; i++) {
|
||||||
});
|
route[methods[i]].apply(route, args);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
// del -> delete alias
|
// del -> delete alias
|
||||||
|
|
||||||
app.del = deprecate(app.delete, 'app.del: Use app.delete instead');
|
app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the given view `name` name with `options`
|
* Render the given view `name` name with `options`
|
||||||
|
@ -463,63 +540,73 @@ app.del = deprecate(app.delete, 'app.del: Use app.delete instead');
|
||||||
* })
|
* })
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {String|Function} options or fn
|
* @param {Object|Function} options or fn
|
||||||
* @param {Function} fn
|
* @param {Function} callback
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.render = function(name, options, fn){
|
app.render = function render(name, options, callback) {
|
||||||
var opts = {};
|
|
||||||
var cache = this.cache;
|
var cache = this.cache;
|
||||||
|
var done = callback;
|
||||||
var engines = this.engines;
|
var engines = this.engines;
|
||||||
|
var opts = options;
|
||||||
|
var renderOptions = {};
|
||||||
var view;
|
var view;
|
||||||
|
|
||||||
// support callback function as second arg
|
// support callback function as second arg
|
||||||
if ('function' == typeof options) {
|
if (typeof options === 'function') {
|
||||||
fn = options, options = {};
|
done = options;
|
||||||
|
opts = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge app.locals
|
// merge app.locals
|
||||||
mixin(opts, this.locals);
|
merge(renderOptions, this.locals);
|
||||||
|
|
||||||
// merge options._locals
|
// merge options._locals
|
||||||
if (options._locals) mixin(opts, options._locals);
|
if (opts._locals) {
|
||||||
|
merge(renderOptions, opts._locals);
|
||||||
|
}
|
||||||
|
|
||||||
// merge options
|
// merge options
|
||||||
mixin(opts, options);
|
merge(renderOptions, opts);
|
||||||
|
|
||||||
// set .cache unless explicitly provided
|
// set .cache unless explicitly provided
|
||||||
opts.cache = null == opts.cache
|
if (renderOptions.cache == null) {
|
||||||
? this.enabled('view cache')
|
renderOptions.cache = this.enabled('view cache');
|
||||||
: opts.cache;
|
}
|
||||||
|
|
||||||
// primed cache
|
// primed cache
|
||||||
if (opts.cache) view = cache[name];
|
if (renderOptions.cache) {
|
||||||
|
view = cache[name];
|
||||||
|
}
|
||||||
|
|
||||||
// view
|
// view
|
||||||
if (!view) {
|
if (!view) {
|
||||||
view = new (this.get('view'))(name, {
|
var View = this.get('view');
|
||||||
|
|
||||||
|
view = new View(name, {
|
||||||
defaultEngine: this.get('view engine'),
|
defaultEngine: this.get('view engine'),
|
||||||
root: this.get('views'),
|
root: this.get('views'),
|
||||||
engines: engines
|
engines: engines
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!view.path) {
|
if (!view.path) {
|
||||||
var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"');
|
var dirs = Array.isArray(view.root) && view.root.length > 1
|
||||||
|
? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"'
|
||||||
|
: 'directory "' + view.root + '"'
|
||||||
|
var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs);
|
||||||
err.view = view;
|
err.view = view;
|
||||||
return fn(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prime the cache
|
// prime the cache
|
||||||
if (opts.cache) cache[name] = view;
|
if (renderOptions.cache) {
|
||||||
|
cache[name] = view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// render
|
// render
|
||||||
try {
|
tryRender(view, renderOptions, done);
|
||||||
view.render(opts, fn);
|
|
||||||
} catch (err) {
|
|
||||||
fn(err);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -540,10 +627,35 @@ app.render = function(name, options, fn){
|
||||||
* https.createServer({ ... }, app).listen(443);
|
* https.createServer({ ... }, app).listen(443);
|
||||||
*
|
*
|
||||||
* @return {http.Server}
|
* @return {http.Server}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.listen = function(){
|
app.listen = function listen() {
|
||||||
var server = http.createServer(this);
|
var server = http.createServer(this);
|
||||||
return server.listen.apply(server, arguments);
|
return server.listen.apply(server, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log error using console.error.
|
||||||
|
*
|
||||||
|
* @param {Error} err
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function logerror(err) {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
if (this.get('env') !== 'test') console.error(err.stack || err.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try rendering a view.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function tryRender(view, options, callback) {
|
||||||
|
try {
|
||||||
|
view.render(options, callback);
|
||||||
|
} catch (err) {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var bodyParser = require('body-parser')
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var mixin = require('utils-merge');
|
var mixin = require('merge-descriptors');
|
||||||
var proto = require('./application');
|
var proto = require('./application');
|
||||||
var Route = require('./router/route');
|
var Route = require('./router/route');
|
||||||
var Router = require('./router');
|
var Router = require('./router');
|
||||||
|
@ -28,11 +39,19 @@ function createApplication() {
|
||||||
app.handle(req, res, next);
|
app.handle(req, res, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
mixin(app, proto);
|
mixin(app, EventEmitter.prototype, false);
|
||||||
mixin(app, EventEmitter.prototype);
|
mixin(app, proto, false);
|
||||||
|
|
||||||
|
// expose the prototype that will get set on requests
|
||||||
|
app.request = Object.create(req, {
|
||||||
|
app: { configurable: true, enumerable: true, writable: true, value: app }
|
||||||
|
})
|
||||||
|
|
||||||
|
// expose the prototype that will get set on responses
|
||||||
|
app.response = Object.create(res, {
|
||||||
|
app: { configurable: true, enumerable: true, writable: true, value: app }
|
||||||
|
})
|
||||||
|
|
||||||
app.request = { __proto__: req, app: app };
|
|
||||||
app.response = { __proto__: res, app: app };
|
|
||||||
app.init();
|
app.init();
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
@ -56,16 +75,18 @@ exports.Router = Router;
|
||||||
* Expose middleware
|
* Expose middleware
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
exports.json = bodyParser.json
|
||||||
exports.query = require('./middleware/query');
|
exports.query = require('./middleware/query');
|
||||||
|
exports.raw = bodyParser.raw
|
||||||
exports.static = require('serve-static');
|
exports.static = require('serve-static');
|
||||||
|
exports.text = bodyParser.text
|
||||||
|
exports.urlencoded = bodyParser.urlencoded
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace removed middleware with an appropriate error message.
|
* Replace removed middleware with an appropriate error message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[
|
var removedMiddlewares = [
|
||||||
'json',
|
|
||||||
'urlencoded',
|
|
||||||
'bodyParser',
|
'bodyParser',
|
||||||
'compress',
|
'compress',
|
||||||
'cookieSession',
|
'cookieSession',
|
||||||
|
@ -82,8 +103,10 @@ exports.static = require('serve-static');
|
||||||
'directory',
|
'directory',
|
||||||
'limit',
|
'limit',
|
||||||
'multipart',
|
'multipart',
|
||||||
'staticCache',
|
'staticCache'
|
||||||
].forEach(function (name) {
|
]
|
||||||
|
|
||||||
|
removedMiddlewares.forEach(function (name) {
|
||||||
Object.defineProperty(exports, name, {
|
Object.defineProperty(exports, name, {
|
||||||
get: function () {
|
get: function () {
|
||||||
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
|
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
|
||||||
|
|
|
@ -1,6 +1,23 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var setPrototypeOf = require('setprototypeof')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization middleware, exposing the
|
* Initialization middleware, exposing the
|
||||||
* request and response to eachother, as well
|
* request and response to each other, as well
|
||||||
* as defaulting the X-Powered-By header field.
|
* as defaulting the X-Powered-By header field.
|
||||||
*
|
*
|
||||||
* @param {Function} app
|
* @param {Function} app
|
||||||
|
@ -15,8 +32,8 @@ exports.init = function(app){
|
||||||
res.req = req;
|
res.req = req;
|
||||||
req.next = next;
|
req.next = next;
|
||||||
|
|
||||||
req.__proto__ = app.request;
|
setPrototypeOf(req, app.request)
|
||||||
res.__proto__ = app.response;
|
setPrototypeOf(res, app.response)
|
||||||
|
|
||||||
res.locals = res.locals || Object.create(null);
|
res.locals = res.locals || Object.create(null);
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,45 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var qs = require('qs');
|
var merge = require('utils-merge')
|
||||||
var parseUrl = require('parseurl');
|
var parseUrl = require('parseurl');
|
||||||
|
var qs = require('qs');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query:
|
|
||||||
*
|
|
||||||
* Automatically parse the query-string when available,
|
|
||||||
* populating the `req.query` object using
|
|
||||||
* [qs](https://github.com/visionmedia/node-querystring).
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
*
|
|
||||||
* .use(connect.query())
|
|
||||||
* .use(function(req, res){
|
|
||||||
* res.end(JSON.stringify(req.query));
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* The `options` passed are provided to qs.parse function.
|
|
||||||
*
|
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @return {Function}
|
* @return {Function}
|
||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = function query(options){
|
module.exports = function query(options) {
|
||||||
|
var opts = merge({}, options)
|
||||||
|
var queryparse = qs.parse;
|
||||||
|
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
queryparse = options;
|
||||||
|
opts = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts !== undefined && opts.allowPrototypes === undefined) {
|
||||||
|
// back-compat for qs module
|
||||||
|
opts.allowPrototypes = true;
|
||||||
|
}
|
||||||
|
|
||||||
return function query(req, res, next){
|
return function query(req, res, next){
|
||||||
if (!req.query) {
|
if (!req.query) {
|
||||||
req.query = ~req.url.indexOf('?')
|
var val = parseUrl(req).query;
|
||||||
? qs.parse(parseUrl(req).query, options)
|
req.query = queryparse(val, opts);
|
||||||
: {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -1,8 +1,21 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var accepts = require('accepts');
|
var accepts = require('accepts');
|
||||||
|
var deprecate = require('depd')('express');
|
||||||
|
var isIP = require('net').isIP;
|
||||||
var typeis = require('type-is');
|
var typeis = require('type-is');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var fresh = require('fresh');
|
var fresh = require('fresh');
|
||||||
|
@ -12,11 +25,17 @@ var proxyaddr = require('proxy-addr');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request prototype.
|
* Request prototype.
|
||||||
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var req = exports = module.exports = {
|
var req = Object.create(http.IncomingMessage.prototype)
|
||||||
__proto__: http.IncomingMessage.prototype
|
|
||||||
};
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = req
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return request header.
|
* Return request header.
|
||||||
|
@ -39,18 +58,28 @@ var req = exports = module.exports = {
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.get =
|
req.get =
|
||||||
req.header = function(name){
|
req.header = function header(name) {
|
||||||
switch (name = name.toLowerCase()) {
|
if (!name) {
|
||||||
|
throw new TypeError('name argument is required to req.get');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof name !== 'string') {
|
||||||
|
throw new TypeError('name must be a string to req.get');
|
||||||
|
}
|
||||||
|
|
||||||
|
var lc = name.toLowerCase();
|
||||||
|
|
||||||
|
switch (lc) {
|
||||||
case 'referer':
|
case 'referer':
|
||||||
case 'referrer':
|
case 'referrer':
|
||||||
return this.headers.referrer
|
return this.headers.referrer
|
||||||
|| this.headers.referer;
|
|| this.headers.referer;
|
||||||
default:
|
default:
|
||||||
return this.headers[name];
|
return this.headers[lc];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,12 +90,12 @@ req.header = function(name){
|
||||||
* the best match when true, otherwise `undefined`, in which
|
* the best match when true, otherwise `undefined`, in which
|
||||||
* case you should respond with 406 "Not Acceptable".
|
* case you should respond with 406 "Not Acceptable".
|
||||||
*
|
*
|
||||||
* The `type` value may be a single mime type string
|
* The `type` value may be a single MIME type string
|
||||||
* such as "application/json", the extension name
|
* such as "application/json", an extension name
|
||||||
* such as "json", a comma-delimted list such as "json, html, text/plain",
|
* such as "json", a comma-delimited list such as "json, html, text/plain",
|
||||||
* an argument list such as `"json", "html", "text/plain"`,
|
* an argument list such as `"json", "html", "text/plain"`,
|
||||||
* or an array `["json", "html", "text/plain"]`. When a list
|
* or an array `["json", "html", "text/plain"]`. When a list
|
||||||
* or array is given the _best_ match, if any is returned.
|
* or array is given, the _best_ match, if any is returned.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
*
|
*
|
||||||
|
@ -96,8 +125,8 @@ req.header = function(name){
|
||||||
* // => "json"
|
* // => "json"
|
||||||
*
|
*
|
||||||
* @param {String|Array} type(s)
|
* @param {String|Array} type(s)
|
||||||
* @return {String}
|
* @return {String|Array|Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.accepts = function(){
|
req.accepts = function(){
|
||||||
|
@ -106,77 +135,84 @@ req.accepts = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given `encoding` is accepted.
|
* Check if the given `encoding`s are accepted.
|
||||||
*
|
*
|
||||||
* @param {String} encoding
|
* @param {String} ...encoding
|
||||||
* @return {Boolean}
|
* @return {String|Array}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.acceptsEncoding = // backwards compatibility
|
|
||||||
req.acceptsEncodings = function(){
|
req.acceptsEncodings = function(){
|
||||||
var accept = accepts(this);
|
var accept = accepts(this);
|
||||||
return accept.encodings.apply(accept, arguments);
|
return accept.encodings.apply(accept, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
req.acceptsEncoding = deprecate.function(req.acceptsEncodings,
|
||||||
|
'req.acceptsEncoding: Use acceptsEncodings instead');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To do: update docs.
|
* Check if the given `charset`s are acceptable,
|
||||||
*
|
|
||||||
* Check if the given `charset` is acceptable,
|
|
||||||
* otherwise you should respond with 406 "Not Acceptable".
|
* otherwise you should respond with 406 "Not Acceptable".
|
||||||
*
|
*
|
||||||
* @param {String} charset
|
* @param {String} ...charset
|
||||||
* @return {Boolean}
|
* @return {String|Array}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.acceptsCharset = // backwards compatibility
|
|
||||||
req.acceptsCharsets = function(){
|
req.acceptsCharsets = function(){
|
||||||
var accept = accepts(this);
|
var accept = accepts(this);
|
||||||
return accept.charsets.apply(accept, arguments);
|
return accept.charsets.apply(accept, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
req.acceptsCharset = deprecate.function(req.acceptsCharsets,
|
||||||
|
'req.acceptsCharset: Use acceptsCharsets instead');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To do: update docs.
|
* Check if the given `lang`s are acceptable,
|
||||||
*
|
|
||||||
* Check if the given `lang` is acceptable,
|
|
||||||
* otherwise you should respond with 406 "Not Acceptable".
|
* otherwise you should respond with 406 "Not Acceptable".
|
||||||
*
|
*
|
||||||
* @param {String} lang
|
* @param {String} ...lang
|
||||||
* @return {Boolean}
|
* @return {String|Array}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.acceptsLanguage = // backwards compatibility
|
|
||||||
req.acceptsLanguages = function(){
|
req.acceptsLanguages = function(){
|
||||||
var accept = accepts(this);
|
var accept = accepts(this);
|
||||||
return accept.languages.apply(accept, arguments);
|
return accept.languages.apply(accept, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
req.acceptsLanguage = deprecate.function(req.acceptsLanguages,
|
||||||
|
'req.acceptsLanguage: Use acceptsLanguages instead');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse Range header field,
|
* Parse Range header field, capping to the given `size`.
|
||||||
* capping to the given `size`.
|
|
||||||
*
|
*
|
||||||
* Unspecified ranges such as "0-" require
|
* Unspecified ranges such as "0-" require knowledge of your resource length. In
|
||||||
* knowledge of your resource length. In
|
* the case of a byte range this is of course the total number of bytes. If the
|
||||||
* the case of a byte range this is of course
|
* Range header field is not given `undefined` is returned, `-1` when unsatisfiable,
|
||||||
* the total number of bytes. If the Range
|
* and `-2` when syntactically invalid.
|
||||||
* header field is not given `null` is returned,
|
|
||||||
* `-1` when unsatisfiable, `-2` when syntactically invalid.
|
|
||||||
*
|
*
|
||||||
* NOTE: remember that ranges are inclusive, so
|
* When ranges are returned, the array has a "type" property which is the type of
|
||||||
* for example "Range: users=0-3" should respond
|
* range that is required (most commonly, "bytes"). Each array element is an object
|
||||||
* with 4 users when available, not 3.
|
* with a "start" and "end" property for the portion of the range.
|
||||||
*
|
*
|
||||||
* @param {Number} size
|
* The "combine" option can be set to `true` and overlapping & adjacent ranges
|
||||||
* @return {Array}
|
* will be combined into a single range.
|
||||||
* @api public
|
*
|
||||||
|
* NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
|
||||||
|
* should respond with 4 users when available, not 3.
|
||||||
|
*
|
||||||
|
* @param {number} size
|
||||||
|
* @param {object} [options]
|
||||||
|
* @param {boolean} [options.combine=false]
|
||||||
|
* @return {number|array}
|
||||||
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.range = function(size){
|
req.range = function range(size, options) {
|
||||||
var range = this.get('Range');
|
var range = this.get('Range');
|
||||||
if (!range) return;
|
if (!range) return;
|
||||||
return parseRange(size, range);
|
return parseRange(size, range, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -193,22 +229,29 @@ req.range = function(size){
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {Mixed} [defaultValue]
|
* @param {Mixed} [defaultValue]
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.param = function(name, defaultValue){
|
req.param = function param(name, defaultValue) {
|
||||||
var params = this.params || {};
|
var params = this.params || {};
|
||||||
var body = this.body || {};
|
var body = this.body || {};
|
||||||
var query = this.query || {};
|
var query = this.query || {};
|
||||||
|
|
||||||
|
var args = arguments.length === 1
|
||||||
|
? 'name'
|
||||||
|
: 'name, default';
|
||||||
|
deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead');
|
||||||
|
|
||||||
if (null != params[name] && params.hasOwnProperty(name)) return params[name];
|
if (null != params[name] && params.hasOwnProperty(name)) return params[name];
|
||||||
if (null != body[name]) return body[name];
|
if (null != body[name]) return body[name];
|
||||||
if (null != query[name]) return query[name];
|
if (null != query[name]) return query[name];
|
||||||
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the incoming request contains the "Content-Type"
|
* Check if the incoming request contains the "Content-Type"
|
||||||
* header field, and it contains the give mime `type`.
|
* header field, and it contains the given mime `type`.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
*
|
*
|
||||||
|
@ -227,54 +270,70 @@ req.param = function(name, defaultValue){
|
||||||
* req.is('html');
|
* req.is('html');
|
||||||
* // => false
|
* // => false
|
||||||
*
|
*
|
||||||
* @param {String} type
|
* @param {String|Array} types...
|
||||||
* @return {Boolean}
|
* @return {String|false|null}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.is = function(types){
|
req.is = function is(types) {
|
||||||
if (!Array.isArray(types)) types = [].slice.call(arguments);
|
var arr = types;
|
||||||
return typeis(this, types);
|
|
||||||
|
// support flattened arguments
|
||||||
|
if (!Array.isArray(types)) {
|
||||||
|
arr = new Array(arguments.length);
|
||||||
|
for (var i = 0; i < arr.length; i++) {
|
||||||
|
arr[i] = arguments[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeis(this, arr);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the protocol string "http" or "https"
|
* Return the protocol string "http" or "https"
|
||||||
* when requested with TLS. When the "trust proxy"
|
* when requested with TLS. When the "trust proxy"
|
||||||
* setting trusts the socket address, the
|
* setting trusts the socket address, the
|
||||||
* "X-Forwarded-Proto" header field will be trusted.
|
* "X-Forwarded-Proto" header field will be trusted
|
||||||
|
* and used if present.
|
||||||
|
*
|
||||||
* If you're running behind a reverse proxy that
|
* If you're running behind a reverse proxy that
|
||||||
* supplies https for you this may be enabled.
|
* supplies https for you this may be enabled.
|
||||||
*
|
*
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('protocol', function(){
|
defineGetter(req, 'protocol', function protocol(){
|
||||||
|
var proto = this.connection.encrypted
|
||||||
|
? 'https'
|
||||||
|
: 'http';
|
||||||
var trust = this.app.get('trust proxy fn');
|
var trust = this.app.get('trust proxy fn');
|
||||||
|
|
||||||
if (!trust(this.connection.remoteAddress)) {
|
if (!trust(this.connection.remoteAddress, 0)) {
|
||||||
return this.connection.encrypted
|
return proto;
|
||||||
? 'https'
|
|
||||||
: 'http';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: X-Forwarded-Proto is normally only ever a
|
// Note: X-Forwarded-Proto is normally only ever a
|
||||||
// single value, but this is to be safe.
|
// single value, but this is to be safe.
|
||||||
var proto = this.get('X-Forwarded-Proto') || 'http';
|
var header = this.get('X-Forwarded-Proto') || proto
|
||||||
return proto.split(/\s*,\s*/)[0];
|
var index = header.indexOf(',')
|
||||||
|
|
||||||
|
return index !== -1
|
||||||
|
? header.substring(0, index).trim()
|
||||||
|
: header.trim()
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Short-hand for:
|
* Short-hand for:
|
||||||
*
|
*
|
||||||
* req.protocol == 'https'
|
* req.protocol === 'https'
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('secure', function(){
|
defineGetter(req, 'secure', function secure(){
|
||||||
return 'https' == this.protocol;
|
return this.protocol === 'https';
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -284,10 +343,10 @@ req.__defineGetter__('secure', function(){
|
||||||
* "trust proxy" is set.
|
* "trust proxy" is set.
|
||||||
*
|
*
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('ip', function(){
|
defineGetter(req, 'ip', function ip(){
|
||||||
var trust = this.app.get('trust proxy fn');
|
var trust = this.app.get('trust proxy fn');
|
||||||
return proxyaddr(this, trust);
|
return proxyaddr(this, trust);
|
||||||
});
|
});
|
||||||
|
@ -301,13 +360,18 @@ req.__defineGetter__('ip', function(){
|
||||||
* "proxy2" were trusted.
|
* "proxy2" were trusted.
|
||||||
*
|
*
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('ips', function(){
|
defineGetter(req, 'ips', function ips() {
|
||||||
var trust = this.app.get('trust proxy fn');
|
var trust = this.app.get('trust proxy fn');
|
||||||
var addrs = proxyaddr.all(this, trust);
|
var addrs = proxyaddr.all(this, trust);
|
||||||
return addrs.slice(1).reverse();
|
|
||||||
|
// reverse the order (to farthest -> closest)
|
||||||
|
// and remove socket address
|
||||||
|
addrs.reverse().pop()
|
||||||
|
|
||||||
|
return addrs
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -322,45 +386,54 @@ req.__defineGetter__('ips', function(){
|
||||||
* If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
|
* If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
|
||||||
*
|
*
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('subdomains', function(){
|
defineGetter(req, 'subdomains', function subdomains() {
|
||||||
|
var hostname = this.hostname;
|
||||||
|
|
||||||
|
if (!hostname) return [];
|
||||||
|
|
||||||
var offset = this.app.get('subdomain offset');
|
var offset = this.app.get('subdomain offset');
|
||||||
return (this.host || '')
|
var subdomains = !isIP(hostname)
|
||||||
.split('.')
|
? hostname.split('.').reverse()
|
||||||
.reverse()
|
: [hostname];
|
||||||
.slice(offset);
|
|
||||||
|
return subdomains.slice(offset);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Short-hand for `url.parse(req.url).pathname`.
|
* Short-hand for `url.parse(req.url).pathname`.
|
||||||
*
|
*
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('path', function(){
|
defineGetter(req, 'path', function path() {
|
||||||
return parse(this).pathname;
|
return parse(this).pathname;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the "Host" header field hostname.
|
* Parse the "Host" header field to a hostname.
|
||||||
*
|
*
|
||||||
* When the "trust proxy" setting trusts the socket
|
* When the "trust proxy" setting trusts the socket
|
||||||
* address, the "X-Forwarded-Host" header field will
|
* address, the "X-Forwarded-Host" header field will
|
||||||
* be trusted.
|
* be trusted.
|
||||||
*
|
*
|
||||||
* @return {String}
|
* @return {String}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('host', function(){
|
defineGetter(req, 'hostname', function hostname(){
|
||||||
var trust = this.app.get('trust proxy fn');
|
var trust = this.app.get('trust proxy fn');
|
||||||
var host = this.get('X-Forwarded-Host');
|
var host = this.get('X-Forwarded-Host');
|
||||||
|
|
||||||
if (!host || !trust(this.connection.remoteAddress)) {
|
if (!host || !trust(this.connection.remoteAddress, 0)) {
|
||||||
host = this.get('Host');
|
host = this.get('Host');
|
||||||
|
} else if (host.indexOf(',') !== -1) {
|
||||||
|
// Note: X-Forwarded-Host is normally only ever a
|
||||||
|
// single value, but this is to be safe.
|
||||||
|
host = host.substring(0, host.indexOf(',')).trimRight()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!host) return;
|
if (!host) return;
|
||||||
|
@ -371,30 +444,40 @@ req.__defineGetter__('host', function(){
|
||||||
: 0;
|
: 0;
|
||||||
var index = host.indexOf(':', offset);
|
var index = host.indexOf(':', offset);
|
||||||
|
|
||||||
return ~index
|
return index !== -1
|
||||||
? host.substring(0, index)
|
? host.substring(0, index)
|
||||||
: host;
|
: host;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: change req.host to return host in next major
|
||||||
|
|
||||||
|
defineGetter(req, 'host', deprecate.function(function host(){
|
||||||
|
return this.hostname;
|
||||||
|
}, 'req.host: Use req.hostname instead'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the request is fresh, aka
|
* Check if the request is fresh, aka
|
||||||
* Last-Modified and/or the ETag
|
* Last-Modified and/or the ETag
|
||||||
* still match.
|
* still match.
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('fresh', function(){
|
defineGetter(req, 'fresh', function(){
|
||||||
var method = this.method;
|
var method = this.method;
|
||||||
var s = this.res.statusCode;
|
var res = this.res
|
||||||
|
var status = res.statusCode
|
||||||
|
|
||||||
// GET or HEAD for weak freshness validation only
|
// GET or HEAD for weak freshness validation only
|
||||||
if ('GET' != method && 'HEAD' != method) return false;
|
if ('GET' !== method && 'HEAD' !== method) return false;
|
||||||
|
|
||||||
// 2xx or 304 as per rfc2616 14.26
|
// 2xx or 304 as per rfc2616 14.26
|
||||||
if ((s >= 200 && s < 300) || 304 == s) {
|
if ((status >= 200 && status < 300) || 304 === status) {
|
||||||
return fresh(this.headers, this.res._headers);
|
return fresh(this.headers, {
|
||||||
|
'etag': res.get('ETag'),
|
||||||
|
'last-modified': res.get('Last-Modified')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -406,10 +489,10 @@ req.__defineGetter__('fresh', function(){
|
||||||
* resource has changed.
|
* resource has changed.
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('stale', function(){
|
defineGetter(req, 'stale', function stale(){
|
||||||
return !this.fresh;
|
return !this.fresh;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -417,10 +500,26 @@ req.__defineGetter__('stale', function(){
|
||||||
* Check if the request was an _XMLHttpRequest_.
|
* Check if the request was an _XMLHttpRequest_.
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
req.__defineGetter__('xhr', function(){
|
defineGetter(req, 'xhr', function xhr(){
|
||||||
var val = this.get('X-Requested-With') || '';
|
var val = this.get('X-Requested-With') || '';
|
||||||
return 'xmlhttprequest' == val.toLowerCase();
|
return val.toLowerCase() === 'xmlhttprequest';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for creating a getter on an object.
|
||||||
|
*
|
||||||
|
* @param {Object} obj
|
||||||
|
* @param {String} name
|
||||||
|
* @param {Function} getter
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function defineGetter(obj, name, getter) {
|
||||||
|
Object.defineProperty(obj, name, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: getter
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,36 +1,60 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Route = require('./route');
|
var Route = require('./route');
|
||||||
var Layer = require('./layer');
|
var Layer = require('./layer');
|
||||||
var methods = require('methods');
|
var methods = require('methods');
|
||||||
|
var mixin = require('utils-merge');
|
||||||
var debug = require('debug')('express:router');
|
var debug = require('debug')('express:router');
|
||||||
|
var deprecate = require('depd')('express');
|
||||||
|
var flatten = require('array-flatten');
|
||||||
var parseUrl = require('parseurl');
|
var parseUrl = require('parseurl');
|
||||||
|
var setPrototypeOf = require('setprototypeof')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var objectRegExp = /^\[object (\S+)\]$/;
|
||||||
var slice = Array.prototype.slice;
|
var slice = Array.prototype.slice;
|
||||||
|
var toString = Object.prototype.toString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new `Router` with the given `options`.
|
* Initialize a new `Router` with the given `options`.
|
||||||
*
|
*
|
||||||
* @param {Object} options
|
* @param {Object} [options]
|
||||||
* @return {Router} which is an callable function
|
* @return {Router} which is a callable function
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var proto = module.exports = function(options) {
|
var proto = module.exports = function(options) {
|
||||||
options = options || {};
|
var opts = options || {};
|
||||||
|
|
||||||
function router(req, res, next) {
|
function router(req, res, next) {
|
||||||
router.handle(req, res, next);
|
router.handle(req, res, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mixin Router class functions
|
// mixin Router class functions
|
||||||
router.__proto__ = proto;
|
setPrototypeOf(router, proto)
|
||||||
|
|
||||||
router.params = {};
|
router.params = {};
|
||||||
router._params = [];
|
router._params = [];
|
||||||
router.caseSensitive = options.caseSensitive;
|
router.caseSensitive = opts.caseSensitive;
|
||||||
router.strict = options.strict;
|
router.mergeParams = opts.mergeParams;
|
||||||
|
router.strict = opts.strict;
|
||||||
router.stack = [];
|
router.stack = [];
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
|
@ -67,12 +91,13 @@ var proto = module.exports = function(options) {
|
||||||
* @param {String} name
|
* @param {String} name
|
||||||
* @param {Function} fn
|
* @param {Function} fn
|
||||||
* @return {app} for chaining
|
* @return {app} for chaining
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
proto.param = function(name, fn){
|
proto.param = function param(name, fn) {
|
||||||
// param logic
|
// param logic
|
||||||
if ('function' == typeof name) {
|
if (typeof name === 'function') {
|
||||||
|
deprecate('router.param(fn): Refactor to use path params');
|
||||||
this._params.push(name);
|
this._params.push(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +108,8 @@ proto.param = function(name, fn){
|
||||||
var ret;
|
var ret;
|
||||||
|
|
||||||
if (name[0] === ':') {
|
if (name[0] === ':') {
|
||||||
name = name.substr(1);
|
deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.slice(1)) + ', fn) instead')
|
||||||
|
name = name.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < len; ++i) {
|
for (var i = 0; i < len; ++i) {
|
||||||
|
@ -94,7 +120,7 @@ proto.param = function(name, fn){
|
||||||
|
|
||||||
// ensure we end up with a
|
// ensure we end up with a
|
||||||
// middleware function
|
// middleware function
|
||||||
if ('function' != typeof fn) {
|
if ('function' !== typeof fn) {
|
||||||
throw new Error('invalid param() call for ' + name + ', got ' + fn);
|
throw new Error('invalid param() call for ' + name + ', got ' + fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,24 +130,19 @@ proto.param = function(name, fn){
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch a req, res into the router.
|
* Dispatch a req, res into the router.
|
||||||
*
|
* @private
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
proto.handle = function(req, res, done) {
|
proto.handle = function handle(req, res, out) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
debug('dispatching %s %s', req.method, req.url);
|
debug('dispatching %s %s', req.method, req.url);
|
||||||
|
|
||||||
var method = req.method.toLowerCase();
|
|
||||||
|
|
||||||
var search = 1 + req.url.indexOf('?');
|
|
||||||
var pathlength = search ? search - 1 : req.url.length;
|
|
||||||
var fqdn = 1 + req.url.substr(0, pathlength).indexOf('://');
|
|
||||||
var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : '';
|
|
||||||
var idx = 0;
|
var idx = 0;
|
||||||
|
var protohost = getProtohost(req.url) || ''
|
||||||
var removed = '';
|
var removed = '';
|
||||||
var slashAdded = false;
|
var slashAdded = false;
|
||||||
|
var sync = 0
|
||||||
var paramcalled = {};
|
var paramcalled = {};
|
||||||
|
|
||||||
// store options for OPTIONS request
|
// store options for OPTIONS request
|
||||||
|
@ -132,150 +153,189 @@ proto.handle = function(req, res, done) {
|
||||||
var stack = self.stack;
|
var stack = self.stack;
|
||||||
|
|
||||||
// manage inter-router variables
|
// manage inter-router variables
|
||||||
var parent = req.next;
|
var parentParams = req.params;
|
||||||
var parentUrl = req.baseUrl || '';
|
var parentUrl = req.baseUrl || '';
|
||||||
done = wrap(done, function(old, err) {
|
var done = restore(out, req, 'baseUrl', 'next', 'params');
|
||||||
req.baseUrl = parentUrl;
|
|
||||||
req.next = parent;
|
// setup next layer
|
||||||
old(err);
|
|
||||||
});
|
|
||||||
req.next = next;
|
req.next = next;
|
||||||
|
|
||||||
// for options requests, respond with a default if nothing else responds
|
// for options requests, respond with a default if nothing else responds
|
||||||
if (method === 'options') {
|
if (req.method === 'OPTIONS') {
|
||||||
done = wrap(done, function(old, err) {
|
done = wrap(done, function(old, err) {
|
||||||
if (err || options.length === 0) return old(err);
|
if (err || options.length === 0) return old(err);
|
||||||
|
sendOptionsResponse(res, options, old);
|
||||||
var body = options.join(',');
|
|
||||||
return res.set('Allow', body).send(body);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup basic req values
|
||||||
|
req.baseUrl = parentUrl;
|
||||||
|
req.originalUrl = req.originalUrl || req.url;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|
||||||
function next(err) {
|
function next(err) {
|
||||||
if (err === 'route') {
|
var layerError = err === 'route'
|
||||||
err = undefined;
|
? null
|
||||||
}
|
: err;
|
||||||
|
|
||||||
var layer = stack[idx++];
|
|
||||||
var layerPath;
|
|
||||||
|
|
||||||
if (!layer) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// remove added slash
|
||||||
if (slashAdded) {
|
if (slashAdded) {
|
||||||
req.url = req.url.substr(1);
|
req.url = req.url.slice(1)
|
||||||
slashAdded = false;
|
slashAdded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.baseUrl = parentUrl;
|
// restore altered req.url
|
||||||
req.url = protohost + removed + req.url.substr(protohost.length);
|
if (removed.length !== 0) {
|
||||||
req.originalUrl = req.originalUrl || req.url;
|
req.baseUrl = parentUrl;
|
||||||
removed = '';
|
req.url = protohost + removed + req.url.slice(protohost.length)
|
||||||
|
removed = '';
|
||||||
try {
|
|
||||||
var path = parseUrl(req).pathname;
|
|
||||||
if (undefined == path) path = '/';
|
|
||||||
|
|
||||||
if (!layer.match(path)) return next(err);
|
|
||||||
|
|
||||||
// route object and not middleware
|
|
||||||
var route = layer.route;
|
|
||||||
|
|
||||||
// if final route, then we support options
|
|
||||||
if (route) {
|
|
||||||
// we don't run any routes with error first
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
req.route = route;
|
|
||||||
|
|
||||||
// we can now dispatch to the route
|
|
||||||
if (method === 'options' && !route.methods['options']) {
|
|
||||||
options.push.apply(options, route._options());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Capture one-time layer values
|
|
||||||
req.params = layer.params;
|
|
||||||
layerPath = layer.path;
|
|
||||||
|
|
||||||
// this should be done for the layer
|
|
||||||
return self.process_params(layer, paramcalled, req, res, function(err) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (route) {
|
|
||||||
return layer.handle(req, res, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
trim_prefix();
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
next(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function trim_prefix() {
|
// signal to exit router
|
||||||
var c = path[layerPath.length];
|
if (layerError === 'router') {
|
||||||
if (c && '/' != c && '.' != c) return next(err);
|
setImmediate(done, null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// no more matching layers
|
||||||
|
if (idx >= stack.length) {
|
||||||
|
setImmediate(done, layerError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// max sync stack
|
||||||
|
if (++sync > 100) {
|
||||||
|
return setImmediate(next, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get pathname of request
|
||||||
|
var path = getPathname(req);
|
||||||
|
|
||||||
|
if (path == null) {
|
||||||
|
return done(layerError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find next matching layer
|
||||||
|
var layer;
|
||||||
|
var match;
|
||||||
|
var route;
|
||||||
|
|
||||||
|
while (match !== true && idx < stack.length) {
|
||||||
|
layer = stack[idx++];
|
||||||
|
match = matchLayer(layer, path);
|
||||||
|
route = layer.route;
|
||||||
|
|
||||||
|
if (typeof match !== 'boolean') {
|
||||||
|
// hold on to layerError
|
||||||
|
layerError = layerError || match;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match !== true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!route) {
|
||||||
|
// process non-route handlers normally
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layerError) {
|
||||||
|
// routes do not match with a pending error
|
||||||
|
match = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var method = req.method;
|
||||||
|
var has_method = route._handles_method(method);
|
||||||
|
|
||||||
|
// build up automatic options response
|
||||||
|
if (!has_method && method === 'OPTIONS') {
|
||||||
|
appendMethods(options, route._options());
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't even bother matching route
|
||||||
|
if (!has_method && method !== 'HEAD') {
|
||||||
|
match = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no match
|
||||||
|
if (match !== true) {
|
||||||
|
return done(layerError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store route for dispatch on change
|
||||||
|
if (route) {
|
||||||
|
req.route = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture one-time layer values
|
||||||
|
req.params = self.mergeParams
|
||||||
|
? mergeParams(layer.params, parentParams)
|
||||||
|
: layer.params;
|
||||||
|
var layerPath = layer.path;
|
||||||
|
|
||||||
|
// this should be done for the layer
|
||||||
|
self.process_params(layer, paramcalled, req, res, function (err) {
|
||||||
|
if (err) {
|
||||||
|
next(layerError || err)
|
||||||
|
} else if (route) {
|
||||||
|
layer.handle_request(req, res, next)
|
||||||
|
} else {
|
||||||
|
trim_prefix(layer, layerError, layerPath, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
sync = 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim_prefix(layer, layerError, layerPath, path) {
|
||||||
|
if (layerPath.length !== 0) {
|
||||||
|
// Validate path is a prefix match
|
||||||
|
if (layerPath !== path.slice(0, layerPath.length)) {
|
||||||
|
next(layerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate path breaks on a path separator
|
||||||
|
var c = path[layerPath.length]
|
||||||
|
if (c && c !== '/' && c !== '.') return next(layerError)
|
||||||
|
|
||||||
// Trim off the part of the url that matches the route
|
// Trim off the part of the url that matches the route
|
||||||
// middleware (.use stuff) needs to have the path stripped
|
// middleware (.use stuff) needs to have the path stripped
|
||||||
|
debug('trim prefix (%s) from url %s', layerPath, req.url);
|
||||||
removed = layerPath;
|
removed = layerPath;
|
||||||
if (removed.length) {
|
req.url = protohost + req.url.slice(protohost.length + removed.length)
|
||||||
debug('trim prefix (%s) from url %s', layerPath, req.url);
|
|
||||||
req.url = protohost + req.url.substr(protohost.length + removed.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure leading slash
|
// Ensure leading slash
|
||||||
if (!fqdn && req.url[0] !== '/') {
|
if (!protohost && req.url[0] !== '/') {
|
||||||
req.url = '/' + req.url;
|
req.url = '/' + req.url;
|
||||||
slashAdded = true;
|
slashAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup base URL (no trailing slash)
|
// Setup base URL (no trailing slash)
|
||||||
if (removed.length && removed.substr(-1) === '/') {
|
req.baseUrl = parentUrl + (removed[removed.length - 1] === '/'
|
||||||
req.baseUrl = parentUrl + removed.substring(0, removed.length - 1);
|
? removed.substring(0, removed.length - 1)
|
||||||
} else {
|
: removed);
|
||||||
req.baseUrl = parentUrl + removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug('%s %s : %s', layer.handle.name || 'anonymous', layerPath, req.originalUrl);
|
|
||||||
var arity = layer.handle.length;
|
|
||||||
try {
|
|
||||||
if (err && arity === 4) {
|
|
||||||
layer.handle(err, req, res, next);
|
|
||||||
} else if (!err && arity < 4) {
|
|
||||||
layer.handle(req, res, next);
|
|
||||||
} else {
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function wrap(old, fn) {
|
debug('%s %s : %s', layer.name, layerPath, req.originalUrl);
|
||||||
return function () {
|
|
||||||
var args = [old].concat(slice.call(arguments));
|
if (layerError) {
|
||||||
fn.apply(this, args);
|
layer.handle_error(layerError, req, res, next);
|
||||||
};
|
} else {
|
||||||
|
layer.handle_request(req, res, next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process any parameters for the layer.
|
* Process any parameters for the layer.
|
||||||
*
|
* @private
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
proto.process_params = function(layer, called, req, res, done) {
|
proto.process_params = function process_params(layer, called, req, res, done) {
|
||||||
var params = this.params;
|
var params = this.params;
|
||||||
|
|
||||||
// captured parameters from the layer, keys and values
|
// captured parameters from the layer, keys and values
|
||||||
|
@ -307,11 +367,6 @@ proto.process_params = function(layer, called, req, res, done) {
|
||||||
|
|
||||||
paramIndex = 0;
|
paramIndex = 0;
|
||||||
key = keys[i++];
|
key = keys[i++];
|
||||||
|
|
||||||
if (!key) {
|
|
||||||
return done();
|
|
||||||
}
|
|
||||||
|
|
||||||
name = key.name;
|
name = key.name;
|
||||||
paramVal = req.params[name];
|
paramVal = req.params[name];
|
||||||
paramCallbacks = params[name];
|
paramCallbacks = params[name];
|
||||||
|
@ -322,7 +377,8 @@ proto.process_params = function(layer, called, req, res, done) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// param previously called with same value or error occurred
|
// param previously called with same value or error occurred
|
||||||
if (paramCalled && (paramCalled.error || paramCalled.match === paramVal)) {
|
if (paramCalled && (paramCalled.match === paramVal
|
||||||
|
|| (paramCalled.error && paramCalled.error !== 'route'))) {
|
||||||
// restore value
|
// restore value
|
||||||
req.params[name] = paramCalled.value;
|
req.params[name] = paramCalled.value;
|
||||||
|
|
||||||
|
@ -336,11 +392,7 @@ proto.process_params = function(layer, called, req, res, done) {
|
||||||
value: paramVal
|
value: paramVal
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
paramCallback();
|
||||||
return paramCallback();
|
|
||||||
} catch (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// single param callbacks
|
// single param callbacks
|
||||||
|
@ -359,7 +411,11 @@ proto.process_params = function(layer, called, req, res, done) {
|
||||||
|
|
||||||
if (!fn) return param();
|
if (!fn) return param();
|
||||||
|
|
||||||
fn(req, res, paramCallback, paramVal, key.name);
|
try {
|
||||||
|
fn(req, res, paramCallback, paramVal, key.name);
|
||||||
|
} catch (e) {
|
||||||
|
paramCallback(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
param();
|
param();
|
||||||
|
@ -377,40 +433,56 @@ proto.process_params = function(layer, called, req, res, done) {
|
||||||
* handlers can operate without any code changes regardless of the "prefix"
|
* handlers can operate without any code changes regardless of the "prefix"
|
||||||
* pathname.
|
* pathname.
|
||||||
*
|
*
|
||||||
* @param {String|Function} route
|
* @public
|
||||||
* @param {Function} fn
|
|
||||||
* @return {app} for chaining
|
|
||||||
* @api public
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
proto.use = function(route, fn){
|
proto.use = function use(fn) {
|
||||||
// default route to '/'
|
var offset = 0;
|
||||||
if ('string' != typeof route) {
|
var path = '/';
|
||||||
fn = route;
|
|
||||||
route = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// default path to '/'
|
||||||
|
// disambiguate router.use([fn])
|
||||||
if (typeof fn !== 'function') {
|
if (typeof fn !== 'function') {
|
||||||
var type = {}.toString.call(fn);
|
var arg = fn;
|
||||||
var msg = 'Router.use() requires callback functions but got a ' + type;
|
|
||||||
throw new Error(msg);
|
while (Array.isArray(arg) && arg.length !== 0) {
|
||||||
|
arg = arg[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// first arg is the path
|
||||||
|
if (typeof arg !== 'function') {
|
||||||
|
offset = 1;
|
||||||
|
path = fn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip trailing slash
|
var callbacks = flatten(slice.call(arguments, offset));
|
||||||
if ('/' == route[route.length - 1]) {
|
|
||||||
route = route.slice(0, -1);
|
if (callbacks.length === 0) {
|
||||||
|
throw new TypeError('Router.use() requires a middleware function')
|
||||||
}
|
}
|
||||||
|
|
||||||
var layer = new Layer(route, {
|
for (var i = 0; i < callbacks.length; i++) {
|
||||||
sensitive: this.caseSensitive,
|
var fn = callbacks[i];
|
||||||
strict: this.strict,
|
|
||||||
end: false
|
|
||||||
}, fn);
|
|
||||||
|
|
||||||
// add the middleware
|
if (typeof fn !== 'function') {
|
||||||
debug('use %s %s', route || '/', fn.name || 'anonymous');
|
throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the middleware
|
||||||
|
debug('use %o %s', path, fn.name || '<anonymous>')
|
||||||
|
|
||||||
|
var layer = new Layer(path, {
|
||||||
|
sensitive: this.caseSensitive,
|
||||||
|
strict: false,
|
||||||
|
end: false
|
||||||
|
}, fn);
|
||||||
|
|
||||||
|
layer.route = undefined;
|
||||||
|
|
||||||
|
this.stack.push(layer);
|
||||||
|
}
|
||||||
|
|
||||||
this.stack.push(layer);
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -424,10 +496,10 @@ proto.use = function(route, fn){
|
||||||
*
|
*
|
||||||
* @param {String} path
|
* @param {String} path
|
||||||
* @return {Route}
|
* @return {Route}
|
||||||
* @api public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
proto.route = function(path){
|
proto.route = function route(path) {
|
||||||
var route = new Route(path);
|
var route = new Route(path);
|
||||||
|
|
||||||
var layer = new Layer(path, {
|
var layer = new Layer(path, {
|
||||||
|
@ -446,7 +518,156 @@ proto.route = function(path){
|
||||||
methods.concat('all').forEach(function(method){
|
methods.concat('all').forEach(function(method){
|
||||||
proto[method] = function(path){
|
proto[method] = function(path){
|
||||||
var route = this.route(path)
|
var route = this.route(path)
|
||||||
route[method].apply(route, [].slice.call(arguments, 1));
|
route[method].apply(route, slice.call(arguments, 1));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// append methods to a list of methods
|
||||||
|
function appendMethods(list, addition) {
|
||||||
|
for (var i = 0; i < addition.length; i++) {
|
||||||
|
var method = addition[i];
|
||||||
|
if (list.indexOf(method) === -1) {
|
||||||
|
list.push(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get pathname of request
|
||||||
|
function getPathname(req) {
|
||||||
|
try {
|
||||||
|
return parseUrl(req).pathname;
|
||||||
|
} catch (err) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get get protocol + host for a URL
|
||||||
|
function getProtohost(url) {
|
||||||
|
if (typeof url !== 'string' || url.length === 0 || url[0] === '/') {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
var searchIndex = url.indexOf('?')
|
||||||
|
var pathLength = searchIndex !== -1
|
||||||
|
? searchIndex
|
||||||
|
: url.length
|
||||||
|
var fqdnIndex = url.slice(0, pathLength).indexOf('://')
|
||||||
|
|
||||||
|
return fqdnIndex !== -1
|
||||||
|
? url.substring(0, url.indexOf('/', 3 + fqdnIndex))
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// get type for error message
|
||||||
|
function gettype(obj) {
|
||||||
|
var type = typeof obj;
|
||||||
|
|
||||||
|
if (type !== 'object') {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inspect [[Class]] for objects
|
||||||
|
return toString.call(obj)
|
||||||
|
.replace(objectRegExp, '$1');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match path to a layer.
|
||||||
|
*
|
||||||
|
* @param {Layer} layer
|
||||||
|
* @param {string} path
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function matchLayer(layer, path) {
|
||||||
|
try {
|
||||||
|
return layer.match(path);
|
||||||
|
} catch (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge params with parent params
|
||||||
|
function mergeParams(params, parent) {
|
||||||
|
if (typeof parent !== 'object' || !parent) {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make copy of parent for base
|
||||||
|
var obj = mixin({}, parent);
|
||||||
|
|
||||||
|
// simple non-numeric merging
|
||||||
|
if (!(0 in params) || !(0 in parent)) {
|
||||||
|
return mixin(obj, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var o = 0;
|
||||||
|
|
||||||
|
// determine numeric gaps
|
||||||
|
while (i in params) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (o in parent) {
|
||||||
|
o++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// offset numeric indices in params before merge
|
||||||
|
for (i--; i >= 0; i--) {
|
||||||
|
params[i + o] = params[i];
|
||||||
|
|
||||||
|
// create holes for the merge when necessary
|
||||||
|
if (i < o) {
|
||||||
|
delete params[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mixin(obj, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore obj props after function
|
||||||
|
function restore(fn, obj) {
|
||||||
|
var props = new Array(arguments.length - 2);
|
||||||
|
var vals = new Array(arguments.length - 2);
|
||||||
|
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
props[i] = arguments[i + 2];
|
||||||
|
vals[i] = obj[props[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return function () {
|
||||||
|
// restore vals
|
||||||
|
for (var i = 0; i < props.length; i++) {
|
||||||
|
obj[props[i]] = vals[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn.apply(this, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// send an OPTIONS response
|
||||||
|
function sendOptionsResponse(res, options, next) {
|
||||||
|
try {
|
||||||
|
var body = options.join(',');
|
||||||
|
res.set('Allow', body);
|
||||||
|
res.send(body);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrap a function
|
||||||
|
function wrap(old, fn) {
|
||||||
|
return function proxy() {
|
||||||
|
var args = new Array(arguments.length + 1);
|
||||||
|
|
||||||
|
args[0] = old;
|
||||||
|
for (var i = 0, len = arguments.length; i < len; i++) {
|
||||||
|
args[i + 1] = arguments[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn.apply(this, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,31 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var pathRegexp = require('path-to-regexp');
|
var pathRegexp = require('path-to-regexp');
|
||||||
var debug = require('debug')('express:router:layer');
|
var debug = require('debug')('express:router:layer');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose `Layer`.
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = Layer;
|
module.exports = Layer;
|
||||||
|
@ -16,12 +35,69 @@ function Layer(path, options, fn) {
|
||||||
return new Layer(path, options, fn);
|
return new Layer(path, options, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('new %s', path);
|
debug('new %o', path)
|
||||||
options = options || {};
|
var opts = options || {};
|
||||||
this.regexp = pathRegexp(path, this.keys = [], options);
|
|
||||||
this.handle = fn;
|
this.handle = fn;
|
||||||
|
this.name = fn.name || '<anonymous>';
|
||||||
|
this.params = undefined;
|
||||||
|
this.path = undefined;
|
||||||
|
this.regexp = pathRegexp(path, this.keys = [], opts);
|
||||||
|
|
||||||
|
// set fast path flags
|
||||||
|
this.regexp.fast_star = path === '*'
|
||||||
|
this.regexp.fast_slash = path === '/' && opts.end === false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the error for the layer.
|
||||||
|
*
|
||||||
|
* @param {Error} error
|
||||||
|
* @param {Request} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {function} next
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
Layer.prototype.handle_error = function handle_error(error, req, res, next) {
|
||||||
|
var fn = this.handle;
|
||||||
|
|
||||||
|
if (fn.length !== 4) {
|
||||||
|
// not a standard error handler
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fn(error, req, res, next);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request for the layer.
|
||||||
|
*
|
||||||
|
* @param {Request} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {function} next
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
Layer.prototype.handle_request = function handle(req, res, next) {
|
||||||
|
var fn = this.handle;
|
||||||
|
|
||||||
|
if (fn.length > 3) {
|
||||||
|
// not a standard request handler
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fn(req, res, next);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this route matches `path`, if so
|
* Check if this route matches `path`, if so
|
||||||
* populate `.params`.
|
* populate `.params`.
|
||||||
|
@ -31,37 +107,75 @@ function Layer(path, options, fn) {
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Layer.prototype.match = function(path){
|
Layer.prototype.match = function match(path) {
|
||||||
var keys = this.keys;
|
var match
|
||||||
var params = this.params = {};
|
|
||||||
var m = this.regexp.exec(path);
|
|
||||||
var n = 0;
|
|
||||||
var key;
|
|
||||||
var val;
|
|
||||||
|
|
||||||
if (!m) return false;
|
if (path != null) {
|
||||||
|
// fast path non-ending match for / (any path matches)
|
||||||
this.path = m[0];
|
if (this.regexp.fast_slash) {
|
||||||
|
this.params = {}
|
||||||
for (var i = 1, len = m.length; i < len; ++i) {
|
this.path = ''
|
||||||
key = keys[i - 1];
|
return true
|
||||||
|
|
||||||
try {
|
|
||||||
val = 'string' == typeof m[i]
|
|
||||||
? decodeURIComponent(m[i])
|
|
||||||
: m[i];
|
|
||||||
} catch(e) {
|
|
||||||
var err = new Error("Failed to decode param '" + m[i] + "'");
|
|
||||||
err.status = 400;
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key) {
|
// fast path for * (everything matched in a param)
|
||||||
params[key.name] = val;
|
if (this.regexp.fast_star) {
|
||||||
} else {
|
this.params = {'0': decode_param(path)}
|
||||||
params[n++] = val;
|
this.path = path
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// match the path
|
||||||
|
match = this.regexp.exec(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
this.params = undefined;
|
||||||
|
this.path = undefined;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store values
|
||||||
|
this.params = {};
|
||||||
|
this.path = match[0]
|
||||||
|
|
||||||
|
var keys = this.keys;
|
||||||
|
var params = this.params;
|
||||||
|
|
||||||
|
for (var i = 1; i < match.length; i++) {
|
||||||
|
var key = keys[i - 1];
|
||||||
|
var prop = key.name;
|
||||||
|
var val = decode_param(match[i])
|
||||||
|
|
||||||
|
if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
|
||||||
|
params[prop] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode param value.
|
||||||
|
*
|
||||||
|
* @param {string} val
|
||||||
|
* @return {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function decode_param(val) {
|
||||||
|
if (typeof val !== 'string' || val.length === 0) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return decodeURIComponent(val);
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof URIError) {
|
||||||
|
err.message = 'Failed to decode param \'' + val + '\'';
|
||||||
|
err.status = err.statusCode = 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,34 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var debug = require('debug')('express:router:route');
|
var debug = require('debug')('express:router:route');
|
||||||
|
var flatten = require('array-flatten');
|
||||||
|
var Layer = require('./layer');
|
||||||
var methods = require('methods');
|
var methods = require('methods');
|
||||||
var utils = require('../utils');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose `Route`.
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var slice = Array.prototype.slice;
|
||||||
|
var toString = Object.prototype.toString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module exports.
|
||||||
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = Route;
|
module.exports = Route;
|
||||||
|
@ -16,95 +37,120 @@ module.exports = Route;
|
||||||
* Initialize `Route` with the given `path`,
|
* Initialize `Route` with the given `path`,
|
||||||
*
|
*
|
||||||
* @param {String} path
|
* @param {String} path
|
||||||
* @api private
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Route(path) {
|
function Route(path) {
|
||||||
debug('new %s', path);
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.stack = undefined;
|
this.stack = [];
|
||||||
|
|
||||||
|
debug('new %o', path)
|
||||||
|
|
||||||
// route handlers for various http methods
|
// route handlers for various http methods
|
||||||
this.methods = {};
|
this.methods = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {Array} supported HTTP methods
|
* Determine if the route handles a given method.
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route.prototype._options = function(){
|
Route.prototype._handles_method = function _handles_method(method) {
|
||||||
return Object.keys(this.methods).map(function(method) {
|
if (this.methods._all) {
|
||||||
return method.toUpperCase();
|
return true;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// normalize name
|
||||||
|
var name = typeof method === 'string'
|
||||||
|
? method.toLowerCase()
|
||||||
|
: method
|
||||||
|
|
||||||
|
if (name === 'head' && !this.methods['head']) {
|
||||||
|
name = 'get';
|
||||||
|
}
|
||||||
|
|
||||||
|
return Boolean(this.methods[name]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Array} supported HTTP methods
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route.prototype._options = function _options() {
|
||||||
|
var methods = Object.keys(this.methods);
|
||||||
|
|
||||||
|
// append automatic head
|
||||||
|
if (this.methods.get && !this.methods.head) {
|
||||||
|
methods.push('head');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < methods.length; i++) {
|
||||||
|
// make upper case
|
||||||
|
methods[i] = methods[i].toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return methods;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dispatch req, res into this route
|
* dispatch req, res into this route
|
||||||
*
|
* @private
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route.prototype.dispatch = function(req, res, done){
|
Route.prototype.dispatch = function dispatch(req, res, done) {
|
||||||
var self = this;
|
var idx = 0;
|
||||||
var method = req.method.toLowerCase();
|
var stack = this.stack;
|
||||||
|
var sync = 0
|
||||||
|
|
||||||
|
if (stack.length === 0) {
|
||||||
|
return done();
|
||||||
|
}
|
||||||
|
var method = typeof req.method === 'string'
|
||||||
|
? req.method.toLowerCase()
|
||||||
|
: req.method
|
||||||
|
|
||||||
if (method === 'head' && !this.methods['head']) {
|
if (method === 'head' && !this.methods['head']) {
|
||||||
method = 'get';
|
method = 'get';
|
||||||
}
|
}
|
||||||
|
|
||||||
req.route = self;
|
req.route = this;
|
||||||
|
|
||||||
// single middleware route case
|
next();
|
||||||
if (typeof this.stack === 'function') {
|
|
||||||
this.stack(req, res, done);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var stack = self.stack;
|
function next(err) {
|
||||||
if (!stack) {
|
// signal to exit route
|
||||||
return done();
|
|
||||||
}
|
|
||||||
|
|
||||||
var idx = 0;
|
|
||||||
(function next_layer(err) {
|
|
||||||
if (err && err === 'route') {
|
if (err && err === 'route') {
|
||||||
return done();
|
return done();
|
||||||
}
|
}
|
||||||
|
|
||||||
var layer = stack[idx++];
|
// signal to exit router
|
||||||
|
if (err && err === 'router') {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// max sync stack
|
||||||
|
if (++sync > 100) {
|
||||||
|
return setImmediate(next, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var layer = stack[idx++]
|
||||||
|
|
||||||
|
// end of layers
|
||||||
if (!layer) {
|
if (!layer) {
|
||||||
return done(err);
|
return done(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer.method && layer.method !== method) {
|
if (layer.method && layer.method !== method) {
|
||||||
return next_layer(err);
|
next(err)
|
||||||
|
} else if (err) {
|
||||||
|
layer.handle_error(err, req, res, next);
|
||||||
|
} else {
|
||||||
|
layer.handle_request(req, res, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
var arity = layer.handle.length;
|
sync = 0
|
||||||
if (err) {
|
}
|
||||||
if (arity < 4) {
|
|
||||||
return next_layer(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
layer.handle(err, req, res, next_layer);
|
|
||||||
} catch (err) {
|
|
||||||
next_layer(err);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arity > 3) {
|
|
||||||
return next_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
layer.handle(req, res, next_layer);
|
|
||||||
} catch (err) {
|
|
||||||
next_layer(err);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,57 +181,50 @@ Route.prototype.dispatch = function(req, res, done){
|
||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route.prototype.all = function(){
|
Route.prototype.all = function all() {
|
||||||
var self = this;
|
var handles = flatten(slice.call(arguments));
|
||||||
var callbacks = utils.flatten([].slice.call(arguments));
|
|
||||||
callbacks.forEach(function(fn) {
|
for (var i = 0; i < handles.length; i++) {
|
||||||
if (typeof fn !== 'function') {
|
var handle = handles[i];
|
||||||
var type = {}.toString.call(fn);
|
|
||||||
var msg = 'Route.all() requires callback functions but got a ' + type;
|
if (typeof handle !== 'function') {
|
||||||
throw new Error(msg);
|
var type = toString.call(handle);
|
||||||
|
var msg = 'Route.all() requires a callback function but got a ' + type
|
||||||
|
throw new TypeError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self.stack) {
|
var layer = Layer('/', {}, handle);
|
||||||
self.stack = fn;
|
layer.method = undefined;
|
||||||
}
|
|
||||||
else if (typeof self.stack === 'function') {
|
|
||||||
self.stack = [{ handle: self.stack }, { handle: fn }];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.stack.push({ handle: fn });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return self;
|
this.methods._all = true;
|
||||||
|
this.stack.push(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
methods.forEach(function(method){
|
methods.forEach(function(method){
|
||||||
Route.prototype[method] = function(){
|
Route.prototype[method] = function(){
|
||||||
var self = this;
|
var handles = flatten(slice.call(arguments));
|
||||||
var callbacks = utils.flatten([].slice.call(arguments));
|
|
||||||
|
|
||||||
callbacks.forEach(function(fn) {
|
for (var i = 0; i < handles.length; i++) {
|
||||||
if (typeof fn !== 'function') {
|
var handle = handles[i];
|
||||||
var type = {}.toString.call(fn);
|
|
||||||
var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
|
if (typeof handle !== 'function') {
|
||||||
|
var type = toString.call(handle);
|
||||||
|
var msg = 'Route.' + method + '() requires a callback function but got a ' + type
|
||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('%s %s', method, self.path);
|
debug('%s %o', method, this.path)
|
||||||
|
|
||||||
if (!self.methods[method]) {
|
var layer = Layer('/', {}, handle);
|
||||||
self.methods[method] = true;
|
layer.method = method;
|
||||||
}
|
|
||||||
|
|
||||||
if (!self.stack) {
|
this.methods[method] = true;
|
||||||
self.stack = [];
|
this.stack.push(layer);
|
||||||
}
|
}
|
||||||
else if (typeof self.stack === 'function') {
|
|
||||||
self.stack = [{ handle: self.stack }];
|
|
||||||
}
|
|
||||||
|
|
||||||
self.stack.push({ method: method, handle: fn });
|
return this;
|
||||||
});
|
|
||||||
return self;
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,42 +1,27 @@
|
||||||
|
/*!
|
||||||
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
|
||||||
|
|
||||||
var mime = require('send').mime;
|
|
||||||
var crc32 = require('buffer-crc32');
|
|
||||||
var crypto = require('crypto');
|
|
||||||
var basename = require('path').basename;
|
|
||||||
var deprecate = require('util').deprecate;
|
|
||||||
var proxyaddr = require('proxy-addr');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple detection of charset parameter in content-type
|
|
||||||
*/
|
|
||||||
var charsetRegExp = /;\s*charset\s*=/;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecate function, like core `util.deprecate`,
|
|
||||||
* but with NODE_ENV and color support.
|
|
||||||
*
|
|
||||||
* @param {Function} fn
|
|
||||||
* @param {String} msg
|
|
||||||
* @return {Function}
|
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.deprecate = function(fn, msg){
|
var Buffer = require('safe-buffer').Buffer
|
||||||
if (process.env.NODE_ENV === 'test') return fn;
|
var contentDisposition = require('content-disposition');
|
||||||
|
var contentType = require('content-type');
|
||||||
// prepend module name
|
var deprecate = require('depd')('express');
|
||||||
msg = 'express: ' + msg;
|
var flatten = require('array-flatten');
|
||||||
|
var mime = require('send').mime;
|
||||||
if (process.stderr.isTTY) {
|
var etag = require('etag');
|
||||||
// colorize
|
var proxyaddr = require('proxy-addr');
|
||||||
msg = '\x1b[31;1m' + msg + '\x1b[0m';
|
var qs = require('qs');
|
||||||
}
|
var querystring = require('querystring');
|
||||||
|
|
||||||
return deprecate(fn, msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return strong ETag for `body`.
|
* Return strong ETag for `body`.
|
||||||
|
@ -47,18 +32,7 @@ exports.deprecate = function(fn, msg){
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.etag = function etag(body, encoding){
|
exports.etag = createETagGenerator({ weak: false })
|
||||||
if (body.length === 0) {
|
|
||||||
// fast-path empty body
|
|
||||||
return '"1B2M2Y8AsgTpgAmY7PhCfg=="'
|
|
||||||
}
|
|
||||||
|
|
||||||
var hash = crypto
|
|
||||||
.createHash('md5')
|
|
||||||
.update(body, encoding)
|
|
||||||
.digest('base64')
|
|
||||||
return '"' + hash + '"'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return weak ETag for `body`.
|
* Return weak ETag for `body`.
|
||||||
|
@ -69,18 +43,7 @@ exports.etag = function etag(body, encoding){
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.wetag = function wetag(body, encoding){
|
exports.wetag = createETagGenerator({ weak: true })
|
||||||
if (body.length === 0) {
|
|
||||||
// fast-path empty body
|
|
||||||
return 'W/"0-0"'
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf = Buffer.isBuffer(body)
|
|
||||||
? body
|
|
||||||
: new Buffer(body, encoding)
|
|
||||||
var len = buf.length
|
|
||||||
return 'W/"' + len.toString(16) + '-' + crc32.unsigned(buf) + '"'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if `path` looks absolute.
|
* Check if `path` looks absolute.
|
||||||
|
@ -91,9 +54,9 @@ exports.wetag = function wetag(body, encoding){
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.isAbsolute = function(path){
|
exports.isAbsolute = function(path){
|
||||||
if ('/' == path[0]) return true;
|
if ('/' === path[0]) return true;
|
||||||
if (':' == path[1] && '\\' == path[2]) return true;
|
if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path
|
||||||
if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path
|
if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,18 +67,8 @@ exports.isAbsolute = function(path){
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.flatten = function(arr, ret){
|
exports.flatten = deprecate.function(flatten,
|
||||||
ret = ret || [];
|
'utils.flatten: use array-flatten npm module instead');
|
||||||
var len = arr.length;
|
|
||||||
for (var i = 0; i < len; ++i) {
|
|
||||||
if (Array.isArray(arr[i])) {
|
|
||||||
exports.flatten(arr[i], ret);
|
|
||||||
} else {
|
|
||||||
ret.push(arr[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize the given `type`, for example "html" becomes "text/html".
|
* Normalize the given `type`, for example "html" becomes "text/html".
|
||||||
|
@ -158,36 +111,25 @@ exports.normalizeTypes = function(types){
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.contentDisposition = function(filename){
|
exports.contentDisposition = deprecate.function(contentDisposition,
|
||||||
var ret = 'attachment';
|
'utils.contentDisposition: use content-disposition npm module instead');
|
||||||
if (filename) {
|
|
||||||
filename = basename(filename);
|
|
||||||
// if filename contains non-ascii characters, add a utf-8 version ala RFC 5987
|
|
||||||
ret = /[^\040-\176]/.test(filename)
|
|
||||||
? 'attachment; filename="' + encodeURI(filename) + '"; filename*=UTF-8\'\'' + encodeURI(filename)
|
|
||||||
: 'attachment; filename="' + filename + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse accept params `str` returning an
|
* Parse accept params `str` returning an
|
||||||
* object with `.value`, `.quality` and `.params`.
|
* object with `.value`, `.quality` and `.params`.
|
||||||
* also includes `.originalIndex` for stable sorting
|
|
||||||
*
|
*
|
||||||
* @param {String} str
|
* @param {String} str
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function acceptParams(str, index) {
|
function acceptParams (str) {
|
||||||
var parts = str.split(/ *; */);
|
var parts = str.split(/ *; */);
|
||||||
var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
|
var ret = { value: parts[0], quality: 1, params: {} }
|
||||||
|
|
||||||
for (var i = 1; i < parts.length; ++i) {
|
for (var i = 1; i < parts.length; ++i) {
|
||||||
var pms = parts[i].split(/ *= */);
|
var pms = parts[i].split(/ *= */);
|
||||||
if ('q' == pms[0]) {
|
if ('q' === pms[0]) {
|
||||||
ret.quality = parseFloat(pms[1]);
|
ret.quality = parseFloat(pms[1]);
|
||||||
} else {
|
} else {
|
||||||
ret.params[pms[0]] = pms[1];
|
ret.params[pms[0]] = pms[1];
|
||||||
|
@ -214,6 +156,7 @@ exports.compileETag = function(val) {
|
||||||
|
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case true:
|
case true:
|
||||||
|
case 'weak':
|
||||||
fn = exports.wetag;
|
fn = exports.wetag;
|
||||||
break;
|
break;
|
||||||
case false:
|
case false:
|
||||||
|
@ -221,9 +164,6 @@ exports.compileETag = function(val) {
|
||||||
case 'strong':
|
case 'strong':
|
||||||
fn = exports.etag;
|
fn = exports.etag;
|
||||||
break;
|
break;
|
||||||
case 'weak':
|
|
||||||
fn = exports.wetag;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new TypeError('unknown value for etag function: ' + val);
|
throw new TypeError('unknown value for etag function: ' + val);
|
||||||
}
|
}
|
||||||
|
@ -231,6 +171,39 @@ exports.compileETag = function(val) {
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile "query parser" value to function.
|
||||||
|
*
|
||||||
|
* @param {String|Function} val
|
||||||
|
* @return {Function}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.compileQueryParser = function compileQueryParser(val) {
|
||||||
|
var fn;
|
||||||
|
|
||||||
|
if (typeof val === 'function') {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (val) {
|
||||||
|
case true:
|
||||||
|
case 'simple':
|
||||||
|
fn = querystring.parse;
|
||||||
|
break;
|
||||||
|
case false:
|
||||||
|
fn = newObject;
|
||||||
|
break;
|
||||||
|
case 'extended':
|
||||||
|
fn = parseExtendedQueryString;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new TypeError('unknown value for query parser function: ' + val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile "proxy trust" value to function.
|
* Compile "proxy trust" value to function.
|
||||||
*
|
*
|
||||||
|
@ -254,7 +227,8 @@ exports.compileTrust = function(val) {
|
||||||
|
|
||||||
if (typeof val === 'string') {
|
if (typeof val === 'string') {
|
||||||
// Support comma-separated values
|
// Support comma-separated values
|
||||||
val = val.split(/ *, */);
|
val = val.split(',')
|
||||||
|
.map(function (v) { return v.trim() })
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxyaddr.compile(val || []);
|
return proxyaddr.compile(val || []);
|
||||||
|
@ -269,24 +243,61 @@ exports.compileTrust = function(val) {
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.setCharset = function(type, charset){
|
exports.setCharset = function setCharset(type, charset) {
|
||||||
if (!type || !charset) return type;
|
if (!type || !charset) {
|
||||||
|
return type;
|
||||||
var exists = charsetRegExp.test(type);
|
|
||||||
|
|
||||||
// removing existing charset
|
|
||||||
if (exists) {
|
|
||||||
var parts = type.split(';');
|
|
||||||
|
|
||||||
for (var i = 1; i < parts.length; i++) {
|
|
||||||
if (charsetRegExp.test(';' + parts[i])) {
|
|
||||||
parts.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type = parts.join(';');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type + '; charset=' + charset;
|
// parse type
|
||||||
|
var parsed = contentType.parse(type);
|
||||||
|
|
||||||
|
// set charset
|
||||||
|
parsed.parameters.charset = charset;
|
||||||
|
|
||||||
|
// format type
|
||||||
|
return contentType.format(parsed);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an ETag generator function, generating ETags with
|
||||||
|
* the given options.
|
||||||
|
*
|
||||||
|
* @param {object} options
|
||||||
|
* @return {function}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createETagGenerator (options) {
|
||||||
|
return function generateETag (body, encoding) {
|
||||||
|
var buf = !Buffer.isBuffer(body)
|
||||||
|
? Buffer.from(body, encoding)
|
||||||
|
: body
|
||||||
|
|
||||||
|
return etag(buf, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an extended query string with qs.
|
||||||
|
*
|
||||||
|
* @param {String} str
|
||||||
|
* @return {Object}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parseExtendedQueryString(str) {
|
||||||
|
return qs.parse(str, {
|
||||||
|
allowPrototypes: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return new empty object.
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function newObject() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,36 @@
|
||||||
/**
|
/*!
|
||||||
* Module dependencies.
|
* express
|
||||||
|
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||||
|
* Copyright(c) 2013 Roman Shtylman
|
||||||
|
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var debug = require('debug')('express:view');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var utils = require('./utils');
|
|
||||||
|
/**
|
||||||
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
var dirname = path.dirname;
|
var dirname = path.dirname;
|
||||||
var basename = path.basename;
|
var basename = path.basename;
|
||||||
var extname = path.extname;
|
var extname = path.extname;
|
||||||
var exists = fs.existsSync || path.existsSync;
|
|
||||||
var join = path.join;
|
var join = path.join;
|
||||||
|
var resolve = path.resolve;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose `View`.
|
* Module exports.
|
||||||
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = View;
|
module.exports = View;
|
||||||
|
@ -26,52 +44,139 @@ module.exports = View;
|
||||||
* - `engines` template engine require() cache
|
* - `engines` template engine require() cache
|
||||||
* - `root` root path for view lookup
|
* - `root` root path for view lookup
|
||||||
*
|
*
|
||||||
* @param {String} name
|
* @param {string} name
|
||||||
* @param {Object} options
|
* @param {object} options
|
||||||
* @api private
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function View(name, options) {
|
function View(name, options) {
|
||||||
options = options || {};
|
var opts = options || {};
|
||||||
|
|
||||||
|
this.defaultEngine = opts.defaultEngine;
|
||||||
|
this.ext = extname(name);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.root = options.root;
|
this.root = opts.root;
|
||||||
var engines = options.engines;
|
|
||||||
this.defaultEngine = options.defaultEngine;
|
if (!this.ext && !this.defaultEngine) {
|
||||||
var ext = this.ext = extname(name);
|
throw new Error('No default engine was specified and no extension was provided.');
|
||||||
if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.');
|
}
|
||||||
if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
|
|
||||||
this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
|
var fileName = name;
|
||||||
this.path = this.lookup(name);
|
|
||||||
|
if (!this.ext) {
|
||||||
|
// get extension from default engine name
|
||||||
|
this.ext = this.defaultEngine[0] !== '.'
|
||||||
|
? '.' + this.defaultEngine
|
||||||
|
: this.defaultEngine;
|
||||||
|
|
||||||
|
fileName += this.ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.engines[this.ext]) {
|
||||||
|
// load engine
|
||||||
|
var mod = this.ext.slice(1)
|
||||||
|
debug('require "%s"', mod)
|
||||||
|
|
||||||
|
// default engine export
|
||||||
|
var fn = require(mod).__express
|
||||||
|
|
||||||
|
if (typeof fn !== 'function') {
|
||||||
|
throw new Error('Module "' + mod + '" does not provide a view engine.')
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.engines[this.ext] = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
// store loaded engine
|
||||||
|
this.engine = opts.engines[this.ext];
|
||||||
|
|
||||||
|
// lookup path
|
||||||
|
this.path = this.lookup(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup view by the given `path`
|
* Lookup view by the given `name`
|
||||||
*
|
*
|
||||||
* @param {String} path
|
* @param {string} name
|
||||||
* @return {String}
|
* @private
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
View.prototype.lookup = function(path){
|
View.prototype.lookup = function lookup(name) {
|
||||||
var ext = this.ext;
|
var path;
|
||||||
|
var roots = [].concat(this.root);
|
||||||
|
|
||||||
// <path>.<engine>
|
debug('lookup "%s"', name);
|
||||||
if (!utils.isAbsolute(path)) path = join(this.root, path);
|
|
||||||
if (exists(path)) return path;
|
|
||||||
|
|
||||||
// <path>/index.<engine>
|
for (var i = 0; i < roots.length && !path; i++) {
|
||||||
path = join(dirname(path), basename(path, ext), 'index' + ext);
|
var root = roots[i];
|
||||||
if (exists(path)) return path;
|
|
||||||
|
// resolve the path
|
||||||
|
var loc = resolve(root, name);
|
||||||
|
var dir = dirname(loc);
|
||||||
|
var file = basename(loc);
|
||||||
|
|
||||||
|
// resolve the file
|
||||||
|
path = this.resolve(dir, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render with the given `options` and callback `fn(err, str)`.
|
* Render with the given options.
|
||||||
*
|
*
|
||||||
* @param {Object} options
|
* @param {object} options
|
||||||
* @param {Function} fn
|
* @param {function} callback
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
View.prototype.render = function(options, fn){
|
View.prototype.render = function render(options, callback) {
|
||||||
this.engine(this.path, options, fn);
|
debug('render "%s"', this.path);
|
||||||
|
this.engine(this.path, options, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the file within the given directory.
|
||||||
|
*
|
||||||
|
* @param {string} dir
|
||||||
|
* @param {string} file
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
View.prototype.resolve = function resolve(dir, file) {
|
||||||
|
var ext = this.ext;
|
||||||
|
|
||||||
|
// <path>.<ext>
|
||||||
|
var path = join(dir, file);
|
||||||
|
var stat = tryStat(path);
|
||||||
|
|
||||||
|
if (stat && stat.isFile()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// <path>/index.<ext>
|
||||||
|
path = join(dir, basename(file, ext), 'index' + ext);
|
||||||
|
stat = tryStat(path);
|
||||||
|
|
||||||
|
if (stat && stat.isFile()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a stat, maybe.
|
||||||
|
*
|
||||||
|
* @param {string} path
|
||||||
|
* @return {fs.Stats}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function tryStat(path) {
|
||||||
|
debug('stat "%s"', path);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return fs.statSync(path);
|
||||||
|
} catch (e) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
coverage/
|
|
||||||
test/
|
|
||||||
.travis.yml
|
|
|
@ -1,38 +0,0 @@
|
||||||
|
|
||||||
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
|
|
|
@ -1,101 +0,0 @@
|
||||||
# Accepts
|
|
||||||
|
|
||||||
[![NPM version](https://badge.fury.io/js/accepts.svg)](http://badge.fury.io/js/accepts)
|
|
||||||
[![Build Status](https://travis-ci.org/expressjs/accepts.svg?branch=master)](https://travis-ci.org/expressjs/accepts)
|
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/expressjs/accepts.svg?branch=master)](https://coveralls.io/r/expressjs/accepts)
|
|
||||||
|
|
||||||
Higher level content negotation based on [negotiator](https://github.com/federomero/negotiator). Extracted from [koa](https://github.com/koajs/koa) for general use.
|
|
||||||
|
|
||||||
In addition to negotatior, 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 `*`
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### var accept = new Accepts(req)
|
|
||||||
|
|
||||||
```js
|
|
||||||
var accepts = require('accepts')
|
|
||||||
|
|
||||||
http.createServer(function (req, res) {
|
|
||||||
var accept = accepts(req)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### accept\[property\]\(\)
|
|
||||||
|
|
||||||
Returns all the explicitly accepted content property as an array in descending priority.
|
|
||||||
|
|
||||||
- `accept.types()`
|
|
||||||
- `accept.encodings()`
|
|
||||||
- `accept.charsets()`
|
|
||||||
- `accept.languages()`
|
|
||||||
|
|
||||||
They are also aliased in singular form such as `accept.type()`. `accept.languages()` is also aliased as `accept.langs()`, etc.
|
|
||||||
|
|
||||||
Note: you should almost never do this in a real app as it defeats the purpose of content negotiation.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// in Google Chrome
|
|
||||||
var encodings = accept.encodings() // -> ['sdch', 'gzip', 'deflate']
|
|
||||||
```
|
|
||||||
|
|
||||||
Since you probably don't support `sdch`, you should just supply the encodings you support:
|
|
||||||
|
|
||||||
```js
|
|
||||||
var encoding = accept.encodings('gzip', 'deflate') // -> 'gzip', probably
|
|
||||||
```
|
|
||||||
|
|
||||||
### accept\[property\]\(values, ...\)
|
|
||||||
|
|
||||||
You can either have `values` be an array or have an argument list of values.
|
|
||||||
|
|
||||||
If the client does not accept any `values`, `false` will be returned.
|
|
||||||
If the client accepts any `values`, the preferred `value` will be return.
|
|
||||||
|
|
||||||
For `accept.types()`, shorthand mime types are allowed.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// req.headers.accept = 'application/json'
|
|
||||||
|
|
||||||
accept.types('json') // -> 'json'
|
|
||||||
accept.types('html', 'json') // -> 'json'
|
|
||||||
accept.types('html') // -> false
|
|
||||||
|
|
||||||
// req.headers.accept = ''
|
|
||||||
// which is equivalent to `*`
|
|
||||||
|
|
||||||
accept.types() // -> [], no explicit types
|
|
||||||
accept.types('text/html', 'text/json') // -> 'text/html', since it was first
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2013 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.
|
|
|
@ -1,160 +0,0 @@
|
||||||
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).filter(validMime);
|
|
||||||
var accepts = n.mediaTypes(mimes);
|
|
||||||
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';
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
test
|
|
||||||
build.js
|
|
||||||
|
|
||||||
# OS generated files #
|
|
||||||
######################
|
|
||||||
.DS_Store*
|
|
||||||
# Icon?
|
|
||||||
ehthumbs.db
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Node.js #
|
|
||||||
###########
|
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
|
@ -1,12 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "0.8"
|
|
||||||
- "0.10"
|
|
||||||
- "0.11"
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- node_js: "0.11"
|
|
||||||
fast_finish: true
|
|
||||||
before_install:
|
|
||||||
# remove build script deps before install
|
|
||||||
- node -pe 'f="./package.json";p=require(f);d=p.devDependencies;for(k in d){if("co"===k.substr(0,2))delete d[k]}require("fs").writeFileSync(f,JSON.stringify(p,null,2))'
|
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
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.
|
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
build:
|
|
||||||
node --harmony-generators build.js
|
|
||||||
|
|
||||||
test:
|
|
||||||
node test/mime.js
|
|
||||||
mocha --require should --reporter spec test/test.js
|
|
||||||
|
|
||||||
.PHONY: build test
|
|
|
@ -1,101 +0,0 @@
|
||||||
# mime-types
|
|
||||||
[![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types)
|
|
||||||
|
|
||||||
The ultimate javascript content-type utility.
|
|
||||||
|
|
||||||
### Install
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ npm install mime-types
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 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. Feel free to add more!
|
|
||||||
- Browser support via Browserify and Component by converting lists to JSON files.
|
|
||||||
|
|
||||||
Otherwise, the API is compatible.
|
|
||||||
|
|
||||||
### Adding Types
|
|
||||||
|
|
||||||
If you'd like to add additional types,
|
|
||||||
simply create a PR adding the type to `custom.json` and
|
|
||||||
a reference link to the [sources](SOURCES.md).
|
|
||||||
|
|
||||||
Do __NOT__ edit `mime.json` or `node.json`.
|
|
||||||
Those are pulled using `build.js`.
|
|
||||||
You should only touch `custom.json`.
|
|
||||||
|
|
||||||
## 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'
|
|
||||||
```
|
|
||||||
|
|
||||||
### mime.types[extension] = type
|
|
||||||
|
|
||||||
A map of content-types by extension.
|
|
||||||
|
|
||||||
### mime.extensions[type] = [extensions]
|
|
||||||
|
|
||||||
A map of extensions by content-type.
|
|
||||||
|
|
||||||
### mime.define(types)
|
|
||||||
|
|
||||||
Globally add definitions.
|
|
||||||
`types` must be an object of the form:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
"<content-type>": [extensions...],
|
|
||||||
"<content-type>": [extensions...]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
See the `.json` files in `lib/` for examples.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT](LICENSE)
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
### Sources for custom types
|
|
||||||
|
|
||||||
This is a list of sources for any custom mime types.
|
|
||||||
When adding custom mime types, please link to where you found the mime type,
|
|
||||||
even if it's from an unofficial source.
|
|
||||||
|
|
||||||
- `text/coffeescript` - http://coffeescript.org/#scripts
|
|
||||||
- `text/x-handlebars-template` - https://handlebarsjs.com/#getting-started
|
|
||||||
- `text/x-sass` & `text/x-scss` - https://github.com/janlelis/rubybuntu-mime/blob/master/sass.xml
|
|
||||||
- `text.jsx` - http://facebook.github.io/react/docs/getting-started.html [[2]](https://github.com/facebook/react/blob/f230e0a03154e6f8a616e0da1fb3d97ffa1a6472/vendor/browser-transforms.js#L210)
|
|
||||||
|
|
||||||
[Sources for node.json types](https://github.com/broofa/node-mime/blob/master/types/node.types)
|
|
||||||
|
|
||||||
### Notes on weird types
|
|
||||||
|
|
||||||
- `font/opentype` - This type is technically invalid according to the spec. No valid types begin with `font/`. No-one uses the official type of `application/vnd.ms-opentype` as the community standardized `application/x-font-otf`. However, chrome logs nonsense warnings unless opentype fonts are served with `font/opentype`. [[1]](http://stackoverflow.com/questions/2871655/proper-mime-type-for-fonts)
|
|
16
node_modules/express/node_modules/accepts/node_modules/mime-types/component.json
generated
vendored
16
node_modules/express/node_modules/accepts/node_modules/mime-types/component.json
generated
vendored
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "mime-types",
|
|
||||||
"description": "The ultimate javascript content-type utility.",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"author": {
|
|
||||||
"name": "Jonathan Ong",
|
|
||||||
"email": "me@jongleberry.com",
|
|
||||||
"url": "http://jongleberry.com",
|
|
||||||
"twitter": "https://twitter.com/jongleberry"
|
|
||||||
},
|
|
||||||
"repository": "expressjs/mime-types",
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"scripts": ["lib/index.js"],
|
|
||||||
"json": ["mime.json", "node.json", "custom.json"]
|
|
||||||
}
|
|
27
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/custom.json
generated
vendored
27
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/custom.json
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
{
|
|
||||||
"text/jade": [
|
|
||||||
"jade"
|
|
||||||
],
|
|
||||||
"text/stylus": [
|
|
||||||
"stylus",
|
|
||||||
"styl"
|
|
||||||
],
|
|
||||||
"text/less": [
|
|
||||||
"less"
|
|
||||||
],
|
|
||||||
"text/x-sass": [
|
|
||||||
"sass"
|
|
||||||
],
|
|
||||||
"text/x-scss": [
|
|
||||||
"scss"
|
|
||||||
],
|
|
||||||
"text/coffeescript": [
|
|
||||||
"coffee"
|
|
||||||
],
|
|
||||||
"text/x-handlebars-template": [
|
|
||||||
"hbs"
|
|
||||||
],
|
|
||||||
"text/jsx": [
|
|
||||||
"jsx"
|
|
||||||
]
|
|
||||||
}
|
|
74
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/index.js
generated
vendored
74
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/index.js
generated
vendored
|
@ -1,74 +0,0 @@
|
||||||
|
|
||||||
// types[extension] = type
|
|
||||||
exports.types = Object.create(null)
|
|
||||||
// extensions[type] = [extensions]
|
|
||||||
exports.extensions = Object.create(null)
|
|
||||||
// define more mime types
|
|
||||||
exports.define = define
|
|
||||||
|
|
||||||
// store the json files
|
|
||||||
exports.json = {
|
|
||||||
mime: require('./mime.json'),
|
|
||||||
node: require('./node.json'),
|
|
||||||
custom: require('./custom.json'),
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.lookup = function (string) {
|
|
||||||
if (!string || typeof string !== "string") return false
|
|
||||||
string = string.replace(/.*[\.\/\\]/, '').toLowerCase()
|
|
||||||
if (!string) return false
|
|
||||||
return exports.types[string] || false
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.extension = function (type) {
|
|
||||||
if (!type || typeof type !== "string") return false
|
|
||||||
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) {
|
|
||||||
// special cases
|
|
||||||
switch (type) {
|
|
||||||
case 'application/json': return 'UTF-8'
|
|
||||||
}
|
|
||||||
|
|
||||||
// default text/* to utf-8
|
|
||||||
if (/^text\//.test(type)) return 'UTF-8'
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// backwards compatibility
|
|
||||||
exports.charsets = {
|
|
||||||
lookup: exports.charset
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
define(exports.json.mime)
|
|
||||||
define(exports.json.node)
|
|
||||||
define(exports.json.custom)
|
|
||||||
|
|
||||||
function define(json) {
|
|
||||||
Object.keys(json).forEach(function (type) {
|
|
||||||
var exts = json[type] || []
|
|
||||||
exports.extensions[type] = exports.extensions[type] || []
|
|
||||||
exts.forEach(function (ext) {
|
|
||||||
if (!~exports.extensions[type].indexOf(ext)) exports.extensions[type].push(ext)
|
|
||||||
exports.types[ext] = type
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
3317
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/mime.json
generated
vendored
3317
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/mime.json
generated
vendored
File diff suppressed because it is too large
Load Diff
55
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/node.json
generated
vendored
55
node_modules/express/node_modules/accepts/node_modules/mime-types/lib/node.json
generated
vendored
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"text/vtt": [
|
|
||||||
"vtt"
|
|
||||||
],
|
|
||||||
"application/x-chrome-extension": [
|
|
||||||
"crx"
|
|
||||||
],
|
|
||||||
"text/x-component": [
|
|
||||||
"htc"
|
|
||||||
],
|
|
||||||
"text/cache-manifest": [
|
|
||||||
"manifest"
|
|
||||||
],
|
|
||||||
"application/octet-stream": [
|
|
||||||
"buffer"
|
|
||||||
],
|
|
||||||
"application/mp4": [
|
|
||||||
"m4p"
|
|
||||||
],
|
|
||||||
"audio/mp4": [
|
|
||||||
"m4a"
|
|
||||||
],
|
|
||||||
"video/MP2T": [
|
|
||||||
"ts"
|
|
||||||
],
|
|
||||||
"application/x-web-app-manifest+json": [
|
|
||||||
"webapp"
|
|
||||||
],
|
|
||||||
"text/x-lua": [
|
|
||||||
"lua"
|
|
||||||
],
|
|
||||||
"application/x-lua-bytecode": [
|
|
||||||
"luac"
|
|
||||||
],
|
|
||||||
"text/x-markdown": [
|
|
||||||
"markdown",
|
|
||||||
"md",
|
|
||||||
"mkd"
|
|
||||||
],
|
|
||||||
"text/plain": [
|
|
||||||
"ini"
|
|
||||||
],
|
|
||||||
"application/dash+xml": [
|
|
||||||
"mdp"
|
|
||||||
],
|
|
||||||
"font/opentype": [
|
|
||||||
"otf"
|
|
||||||
],
|
|
||||||
"application/json": [
|
|
||||||
"map"
|
|
||||||
],
|
|
||||||
"application/xml": [
|
|
||||||
"xsd"
|
|
||||||
]
|
|
||||||
}
|
|
42
node_modules/express/node_modules/accepts/node_modules/mime-types/package.json
generated
vendored
42
node_modules/express/node_modules/accepts/node_modules/mime-types/package.json
generated
vendored
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"name": "mime-types",
|
|
||||||
"description": "The ultimate javascript content-type utility.",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"author": {
|
|
||||||
"name": "Jonathan Ong",
|
|
||||||
"email": "me@jongleberry.com",
|
|
||||||
"url": "http://jongleberry.com"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Jeremiah Senkpiel",
|
|
||||||
"email": "fishrock123@rocketmail.com",
|
|
||||||
"url": "https://searchbeam.jit.su"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/expressjs/mime-types"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"main": "lib",
|
|
||||||
"devDependencies": {
|
|
||||||
"co": "3",
|
|
||||||
"cogent": "0",
|
|
||||||
"mocha": "1",
|
|
||||||
"should": "3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "make test"
|
|
||||||
},
|
|
||||||
"readme": "# mime-types\n[![NPM version](https://badge.fury.io/js/mime-types.svg)](https://badge.fury.io/js/mime-types) [![Build Status](https://travis-ci.org/expressjs/mime-types.svg?branch=master)](https://travis-ci.org/expressjs/mime-types)\n\nThe ultimate javascript content-type utility.\n\n### Install\n\n```sh\n$ npm install mime-types\n```\n\n#### Similar to [node-mime](https://github.com/broofa/node-mime), except:\n\n- __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'`.\n- No `new Mime()` business, so you could do `var lookup = require('mime-types').lookup`.\n- Additional mime types are added such as jade and stylus. Feel free to add more!\n- Browser support via Browserify and Component by converting lists to JSON files.\n\nOtherwise, the API is compatible.\n\n### Adding Types\n\nIf you'd like to add additional types,\nsimply create a PR adding the type to `custom.json` and\na reference link to the [sources](SOURCES.md).\n\nDo __NOT__ edit `mime.json` or `node.json`.\nThose are pulled using `build.js`.\nYou should only touch `custom.json`.\n\n## API\n\n```js\nvar mime = require('mime-types')\n```\n\nAll functions return `false` if input is invalid or not found.\n\n### mime.lookup(path)\n\nLookup the content-type associated with a file.\n\n```js\nmime.lookup('json') // 'application/json'\nmime.lookup('.md') // 'text/x-markdown'\nmime.lookup('file.html') // 'text/html'\nmime.lookup('folder/file.js') // 'application/javascript'\n\nmime.lookup('cats') // false\n```\n\n### mime.contentType(type)\n\nCreate a full content-type header given a content-type or extension.\n\n```js\nmime.contentType('markdown') // 'text/x-markdown; charset=utf-8'\nmime.contentType('file.json') // 'application/json; charset=utf-8'\n```\n\n### mime.extension(type)\n\nGet the default extension for a content-type.\n\n```js\nmime.extension('application/octet-stream') // 'bin'\n```\n\n### mime.charset(type)\n\nLookup the implied default charset of a content-type.\n\n```js\nmime.charset('text/x-markdown') // 'UTF-8'\n```\n\n### mime.types[extension] = type\n\nA map of content-types by extension.\n\n### mime.extensions[type] = [extensions]\n\nA map of extensions by content-type.\n\n### mime.define(types)\n\nGlobally add definitions.\n`types` must be an object of the form:\n\n```js\n{\n \"<content-type>\": [extensions...],\n \"<content-type>\": [extensions...]\n}\n```\n\nSee the `.json` files in `lib/` for examples.\n\n## License\n\n[MIT](LICENSE)\n",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/expressjs/mime-types/issues"
|
|
||||||
},
|
|
||||||
"_id": "mime-types@1.0.1",
|
|
||||||
"_from": "mime-types@~1.0.0"
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
examples
|
|
||||||
test
|
|
||||||
.travis.yml
|
|
|
@ -1,27 +0,0 @@
|
||||||
Original "Negotiator" program Copyright Federico Romero
|
|
||||||
Port to JavaScript Copyright Isaac Z. Schlueter
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
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.
|
|
90
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/charset.js
generated
vendored
90
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/charset.js
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
module.exports = preferredCharsets;
|
|
||||||
preferredCharsets.preferredCharsets = preferredCharsets;
|
|
||||||
|
|
||||||
function parseAcceptCharset(accept) {
|
|
||||||
return accept.split(',').map(function(e) {
|
|
||||||
return parseCharset(e.trim());
|
|
||||||
}).filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseCharset(s) {
|
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCharsetPriority(charset, accepted) {
|
|
||||||
return (accepted.map(function(a) {
|
|
||||||
return specify(charset, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q:0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(charset, spec) {
|
|
||||||
var s = 0;
|
|
||||||
if(spec.charset === charset){
|
|
||||||
s |= 1;
|
|
||||||
} else if (spec.charset !== '*' ) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
s: s,
|
|
||||||
q: spec.q,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function preferredCharsets(accept, provided) {
|
|
||||||
// RFC 2616 sec 14.2: no header = *
|
|
||||||
accept = parseAcceptCharset(accept === undefined ? '*' : accept || '');
|
|
||||||
if (provided) {
|
|
||||||
return provided.map(function(type) {
|
|
||||||
return [type, getCharsetPriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type) {
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.charset;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
120
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/encoding.js
generated
vendored
120
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/encoding.js
generated
vendored
|
@ -1,120 +0,0 @@
|
||||||
module.exports = preferredEncodings;
|
|
||||||
preferredEncodings.preferredEncodings = preferredEncodings;
|
|
||||||
|
|
||||||
function parseAcceptEncoding(accept) {
|
|
||||||
var acceptableEncodings;
|
|
||||||
|
|
||||||
if (accept) {
|
|
||||||
acceptableEncodings = accept.split(',').map(function(e) {
|
|
||||||
return parseEncoding(e.trim());
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
acceptableEncodings = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!acceptableEncodings.some(function(e) {
|
|
||||||
return e && specify('identity', e);
|
|
||||||
})) {
|
|
||||||
/*
|
|
||||||
* If identity doesn't explicitly appear in the accept-encoding header,
|
|
||||||
* it's added to the list of acceptable encoding with the lowest q
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
var lowestQ = 1;
|
|
||||||
|
|
||||||
for(var i = 0; i < acceptableEncodings.length; i++){
|
|
||||||
var e = acceptableEncodings[i];
|
|
||||||
if(e && e.q < lowestQ){
|
|
||||||
lowestQ = e.q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acceptableEncodings.push({
|
|
||||||
encoding: 'identity',
|
|
||||||
q: lowestQ / 2,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return acceptableEncodings.filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseEncoding(s) {
|
|
||||||
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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEncodingPriority(encoding, accepted) {
|
|
||||||
return (accepted.map(function(a) {
|
|
||||||
return specify(encoding, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(encoding, spec) {
|
|
||||||
var s = 0;
|
|
||||||
if(spec.encoding === encoding){
|
|
||||||
s |= 1;
|
|
||||||
} else if (spec.encoding !== '*' ) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
s: s,
|
|
||||||
q: spec.q,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function preferredEncodings(accept, provided) {
|
|
||||||
accept = parseAcceptEncoding(accept || '');
|
|
||||||
if (provided) {
|
|
||||||
return provided.map(function(type) {
|
|
||||||
return [type, getEncodingPriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type){
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.encoding;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
103
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/language.js
generated
vendored
103
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/language.js
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
module.exports = preferredLanguages;
|
|
||||||
preferredLanguages.preferredLanguages = preferredLanguages;
|
|
||||||
|
|
||||||
function parseAcceptLanguage(accept) {
|
|
||||||
return accept.split(',').map(function(e) {
|
|
||||||
return parseLanguage(e.trim());
|
|
||||||
}).filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseLanguage(s) {
|
|
||||||
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,
|
|
||||||
full: full
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLanguagePriority(language, accepted) {
|
|
||||||
return (accepted.map(function(a){
|
|
||||||
return specify(language, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(language, spec) {
|
|
||||||
var p = parseLanguage(language)
|
|
||||||
if (!p) return null;
|
|
||||||
var s = 0;
|
|
||||||
if(spec.full === p.full){
|
|
||||||
s |= 4;
|
|
||||||
} else if (spec.prefix === p.full) {
|
|
||||||
s |= 2;
|
|
||||||
} else if (spec.full === p.prefix) {
|
|
||||||
s |= 1;
|
|
||||||
} else if (spec.full !== '*' ) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
s: s,
|
|
||||||
q: spec.q,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function preferredLanguages(accept, provided) {
|
|
||||||
// RFC 2616 sec 14.4: no header = *
|
|
||||||
accept = parseAcceptLanguage(accept === undefined ? '*' : accept || '');
|
|
||||||
if (provided) {
|
|
||||||
|
|
||||||
var ret = provided.map(function(type) {
|
|
||||||
return [type, getLanguagePriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type) {
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.full;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
125
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/mediaType.js
generated
vendored
125
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/mediaType.js
generated
vendored
|
@ -1,125 +0,0 @@
|
||||||
module.exports = preferredMediaTypes;
|
|
||||||
preferredMediaTypes.preferredMediaTypes = preferredMediaTypes;
|
|
||||||
|
|
||||||
function parseAccept(accept) {
|
|
||||||
return accept.split(',').map(function(e) {
|
|
||||||
return parseMediaType(e.trim());
|
|
||||||
}).filter(function(e) {
|
|
||||||
return e;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseMediaType(s) {
|
|
||||||
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,
|
|
||||||
full: full
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMediaTypePriority(type, accepted) {
|
|
||||||
return (accepted.map(function(a) {
|
|
||||||
return specify(type, a);
|
|
||||||
}).filter(Boolean).sort(function (a, b) {
|
|
||||||
if(a.s == b.s) {
|
|
||||||
return a.q > b.q ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return a.s > b.s ? -1 : 1;
|
|
||||||
}
|
|
||||||
})[0] || {s: 0, q: 0});
|
|
||||||
}
|
|
||||||
|
|
||||||
function specify(type, spec) {
|
|
||||||
var p = parseMediaType(type);
|
|
||||||
var s = 0;
|
|
||||||
|
|
||||||
if (!p) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spec.type == p.type) {
|
|
||||||
s |= 4
|
|
||||||
} else if(spec.type != '*') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(spec.subtype == p.subtype) {
|
|
||||||
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] == p.params[k];
|
|
||||||
})) {
|
|
||||||
s |= 1
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
q: spec.q,
|
|
||||||
s: s,
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function preferredMediaTypes(accept, provided) {
|
|
||||||
// RFC 2616 sec 14.2: no header = */*
|
|
||||||
accept = parseAccept(accept === undefined ? '*/*' : accept || '');
|
|
||||||
if (provided) {
|
|
||||||
return provided.map(function(type) {
|
|
||||||
return [type, getMediaTypePriority(type, accept)];
|
|
||||||
}).filter(function(pair) {
|
|
||||||
return pair[1].q > 0;
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
var pa = a[1];
|
|
||||||
var pb = b[1];
|
|
||||||
if(pa.q == pb.q) {
|
|
||||||
return pa.s < pb.s ? 1 : -1;
|
|
||||||
} else {
|
|
||||||
return pa.q < pb.q ? 1 : -1;
|
|
||||||
}
|
|
||||||
}).map(function(pair) {
|
|
||||||
return pair[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return accept.sort(function (a, b) {
|
|
||||||
// revsort
|
|
||||||
return a.q < b.q ? 1 : -1;
|
|
||||||
}).filter(function(type) {
|
|
||||||
return type.q > 0;
|
|
||||||
}).map(function(type) {
|
|
||||||
return type.full;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
37
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/negotiator.js
generated
vendored
37
node_modules/express/node_modules/accepts/node_modules/negotiator/lib/negotiator.js
generated
vendored
|
@ -1,37 +0,0 @@
|
||||||
module.exports = Negotiator;
|
|
||||||
Negotiator.Negotiator = Negotiator;
|
|
||||||
|
|
||||||
function Negotiator(request) {
|
|
||||||
if (!(this instanceof Negotiator)) return new Negotiator(request);
|
|
||||||
this.request = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
var set = { charset: 'accept-charset',
|
|
||||||
encoding: 'accept-encoding',
|
|
||||||
language: 'accept-language',
|
|
||||||
mediaType: 'accept' };
|
|
||||||
|
|
||||||
|
|
||||||
function capitalize(string){
|
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(set).forEach(function (k) {
|
|
||||||
var header = set[k],
|
|
||||||
method = require('./'+k+'.js'),
|
|
||||||
singular = k,
|
|
||||||
plural = k + 's';
|
|
||||||
|
|
||||||
Negotiator.prototype[plural] = function (available) {
|
|
||||||
return method(this.request.headers[header], available);
|
|
||||||
};
|
|
||||||
|
|
||||||
Negotiator.prototype[singular] = function(available) {
|
|
||||||
var set = this[plural](available);
|
|
||||||
if (set) return set[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep preferred* methods for legacy compatibility
|
|
||||||
Negotiator.prototype['preferred'+capitalize(plural)] = Negotiator.prototype[plural];
|
|
||||||
Negotiator.prototype['preferred'+capitalize(singular)] = Negotiator.prototype[singular];
|
|
||||||
})
|
|
49
node_modules/express/node_modules/accepts/node_modules/negotiator/package.json
generated
vendored
49
node_modules/express/node_modules/accepts/node_modules/negotiator/package.json
generated
vendored
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"name": "negotiator",
|
|
||||||
"description": "HTTP content negotiation",
|
|
||||||
"version": "0.4.7",
|
|
||||||
"author": {
|
|
||||||
"name": "Federico Romero",
|
|
||||||
"email": "federico.romero@outboxlabs.com"
|
|
||||||
},
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Isaac Z. Schlueter",
|
|
||||||
"email": "i@izs.me",
|
|
||||||
"url": "http://blog.izs.me/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/federomero/negotiator.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"content negotiation",
|
|
||||||
"accept",
|
|
||||||
"accept-language",
|
|
||||||
"accept-encoding",
|
|
||||||
"accept-charset"
|
|
||||||
],
|
|
||||||
"engine": "node >= 0.6",
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"nodeunit": "0.8.x"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "nodeunit test"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"main": "lib/negotiator.js",
|
|
||||||
"readme": "# Negotiator [![Build Status](https://travis-ci.org/federomero/negotiator.png)](https://travis-ci.org/federomero/negotiator)\n\nAn HTTP content negotiator for node.js written in javascript.\n\n# Accept Negotiation\n\n Negotiator = require('negotiator')\n\n availableMediaTypes = ['text/html', 'text/plain', 'application/json']\n\n // The negotiator constructor receives a request object\n negotiator = new Negotiator(request)\n\n // Let's say Accept header is 'text/html, application/*;q=0.2, image/jpeg;q=0.8'\n\n negotiator.mediaTypes()\n // -> ['text/html', 'image/jpeg', 'application/*']\n\n negotiator.mediaTypes(availableMediaTypes)\n // -> ['text/html', 'application/json']\n\n negotiator.mediaType(availableMediaTypes)\n // -> 'text/html'\n\nYou can check a working example at `examples/accept.js`.\n\n## Methods\n\n`mediaTypes(availableMediaTypes)`:\n\nReturns an array of preferred media types ordered by priority from a list of available media types.\n\n`mediaType(availableMediaType)`:\n\nReturns the top preferred media type from a list of available media types.\n\n# Accept-Language Negotiation\n\n Negotiator = require('negotiator')\n\n negotiator = new Negotiator(request)\n\n availableLanguages = 'en', 'es', 'fr'\n\n // Let's say Accept-Language header is 'en;q=0.8, es, pt'\n\n negotiator.languages()\n // -> ['es', 'pt', 'en']\n\n negotiator.languages(availableLanguages)\n // -> ['es', 'en']\n\n language = negotiator.language(availableLanguages)\n // -> 'es'\n\nYou can check a working example at `examples/language.js`.\n\n## Methods\n\n`languages(availableLanguages)`:\n\nReturns an array of preferred languages ordered by priority from a list of available languages.\n\n`language(availableLanguages)`:\n\nReturns the top preferred language from a list of available languages.\n\n# Accept-Charset Negotiation\n\n Negotiator = require('negotiator')\n\n availableCharsets = ['utf-8', 'iso-8859-1', 'iso-8859-5']\n\n negotiator = new Negotiator(request)\n\n // Let's say Accept-Charset header is 'utf-8, iso-8859-1;q=0.8, utf-7;q=0.2'\n\n negotiator.charsets()\n // -> ['utf-8', 'iso-8859-1', 'utf-7']\n\n negotiator.charsets(availableCharsets)\n // -> ['utf-8', 'iso-8859-1']\n\n negotiator.charset(availableCharsets)\n // -> 'utf-8'\n\nYou can check a working example at `examples/charset.js`.\n\n## Methods\n\n`charsets(availableCharsets)`:\n\nReturns an array of preferred charsets ordered by priority from a list of available charsets.\n\n`charset(availableCharsets)`:\n\nReturns the top preferred charset from a list of available charsets.\n\n# Accept-Encoding Negotiation\n\n Negotiator = require('negotiator').Negotiator\n\n availableEncodings = ['identity', 'gzip']\n\n negotiator = new Negotiator(request)\n\n // Let's say Accept-Encoding header is 'gzip, compress;q=0.2, identity;q=0.5'\n\n negotiator.encodings()\n // -> ['gzip', 'identity', 'compress']\n\n negotiator.encodings(availableEncodings)\n // -> ['gzip', 'identity']\n\n negotiator.encoding(availableEncodings)\n // -> 'gzip'\n\nYou can check a working example at `examples/encoding.js`.\n\n## Methods\n\n`encodings(availableEncodings)`:\n\nReturns an array of preferred encodings ordered by priority from a list of available encodings.\n\n`encoding(availableEncodings)`:\n\nReturns the top preferred encoding from a list of available encodings.\n\n# License\n\nMIT\n",
|
|
||||||
"readmeFilename": "readme.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/federomero/negotiator/issues"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"_id": "negotiator@0.4.7",
|
|
||||||
"_from": "negotiator@0.4.7"
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
# Negotiator [![Build Status](https://travis-ci.org/federomero/negotiator.png)](https://travis-ci.org/federomero/negotiator)
|
|
||||||
|
|
||||||
An HTTP content negotiator for node.js written in javascript.
|
|
||||||
|
|
||||||
# Accept Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator')
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`mediaTypes(availableMediaTypes)`:
|
|
||||||
|
|
||||||
Returns an array of preferred media types ordered by priority from a list of available media types.
|
|
||||||
|
|
||||||
`mediaType(availableMediaType)`:
|
|
||||||
|
|
||||||
Returns the top preferred media type from a list of available media types.
|
|
||||||
|
|
||||||
# Accept-Language Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator')
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`languages(availableLanguages)`:
|
|
||||||
|
|
||||||
Returns an array of preferred languages ordered by priority from a list of available languages.
|
|
||||||
|
|
||||||
`language(availableLanguages)`:
|
|
||||||
|
|
||||||
Returns the top preferred language from a list of available languages.
|
|
||||||
|
|
||||||
# Accept-Charset Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator')
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`charsets(availableCharsets)`:
|
|
||||||
|
|
||||||
Returns an array of preferred charsets ordered by priority from a list of available charsets.
|
|
||||||
|
|
||||||
`charset(availableCharsets)`:
|
|
||||||
|
|
||||||
Returns the top preferred charset from a list of available charsets.
|
|
||||||
|
|
||||||
# Accept-Encoding Negotiation
|
|
||||||
|
|
||||||
Negotiator = require('negotiator').Negotiator
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
`encodings(availableEncodings)`:
|
|
||||||
|
|
||||||
Returns an array of preferred encodings ordered by priority from a list of available encodings.
|
|
||||||
|
|
||||||
`encoding(availableEncodings)`:
|
|
||||||
|
|
||||||
Returns the top preferred encoding from a list of available encodings.
|
|
||||||
|
|
||||||
# License
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"name": "accepts",
|
|
||||||
"description": "Higher-level content negotiation",
|
|
||||||
"version": "1.0.6",
|
|
||||||
"author": {
|
|
||||||
"name": "Jonathan Ong",
|
|
||||||
"email": "me@jongleberry.com",
|
|
||||||
"url": "http://jongleberry.com"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/expressjs/accepts"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"mime-types": "~1.0.0",
|
|
||||||
"negotiator": "0.4.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"istanbul": "0.2.11",
|
|
||||||
"mocha": "*",
|
|
||||||
"should": "*"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "mocha --require should --reporter dot test/",
|
|
||||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require should --reporter dot test/",
|
|
||||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require should --reporter spec test/"
|
|
||||||
},
|
|
||||||
"readme": "# Accepts\n\n[![NPM version](https://badge.fury.io/js/accepts.svg)](http://badge.fury.io/js/accepts)\n[![Build Status](https://travis-ci.org/expressjs/accepts.svg?branch=master)](https://travis-ci.org/expressjs/accepts)\n[![Coverage Status](https://img.shields.io/coveralls/expressjs/accepts.svg?branch=master)](https://coveralls.io/r/expressjs/accepts)\n\nHigher level content negotation based on [negotiator](https://github.com/federomero/negotiator). Extracted from [koa](https://github.com/koajs/koa) for general use.\n\nIn addition to negotatior, it allows:\n\n- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` as well as `('text/html', 'application/json')`.\n- Allows type shorthands such as `json`.\n- Returns `false` when no types match\n- Treats non-existent headers as `*`\n\n## API\n\n### var accept = new Accepts(req)\n\n```js\nvar accepts = require('accepts')\n\nhttp.createServer(function (req, res) {\n var accept = accepts(req)\n})\n```\n\n### accept\\[property\\]\\(\\)\n\nReturns all the explicitly accepted content property as an array in descending priority.\n\n- `accept.types()`\n- `accept.encodings()`\n- `accept.charsets()`\n- `accept.languages()`\n\nThey are also aliased in singular form such as `accept.type()`. `accept.languages()` is also aliased as `accept.langs()`, etc.\n\nNote: you should almost never do this in a real app as it defeats the purpose of content negotiation.\n\nExample:\n\n```js\n// in Google Chrome\nvar encodings = accept.encodings() // -> ['sdch', 'gzip', 'deflate']\n```\n\nSince you probably don't support `sdch`, you should just supply the encodings you support:\n\n```js\nvar encoding = accept.encodings('gzip', 'deflate') // -> 'gzip', probably\n```\n\n### accept\\[property\\]\\(values, ...\\)\n\nYou can either have `values` be an array or have an argument list of values.\n\nIf the client does not accept any `values`, `false` will be returned.\nIf the client accepts any `values`, the preferred `value` will be return.\n\nFor `accept.types()`, shorthand mime types are allowed.\n\nExample:\n\n```js\n// req.headers.accept = 'application/json'\n\naccept.types('json') // -> 'json'\naccept.types('html', 'json') // -> 'json'\naccept.types('html') // -> false\n\n// req.headers.accept = ''\n// which is equivalent to `*`\n\naccept.types() // -> [], no explicit types\naccept.types('text/html', 'text/json') // -> 'text/html', since it was first\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/expressjs/accepts/issues"
|
|
||||||
},
|
|
||||||
"_id": "accepts@1.0.6",
|
|
||||||
"_from": "accepts@~1.0.5"
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
node_modules
|
|
|
@ -1,8 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.6
|
|
||||||
- 0.8
|
|
||||||
notifications:
|
|
||||||
email:
|
|
||||||
recipients:
|
|
||||||
- brianloveswords@gmail.com
|
|
|
@ -1,17 +0,0 @@
|
||||||
Copyright (c) 2013 Brian J. Brennan
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,47 +0,0 @@
|
||||||
# buffer-crc32
|
|
||||||
|
|
||||||
[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)
|
|
||||||
|
|
||||||
crc32 that works with binary data and fancy character sets, outputs
|
|
||||||
buffer, signed or unsigned data and has tests.
|
|
||||||
|
|
||||||
Derived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix
|
|
||||||
|
|
||||||
# install
|
|
||||||
```
|
|
||||||
npm install buffer-crc32
|
|
||||||
```
|
|
||||||
|
|
||||||
# example
|
|
||||||
```js
|
|
||||||
var crc32 = require('buffer-crc32');
|
|
||||||
// works with buffers
|
|
||||||
var buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])
|
|
||||||
crc32(buf) // -> <Buffer 94 5a ab 4a>
|
|
||||||
|
|
||||||
// has convenience methods for getting signed or unsigned ints
|
|
||||||
crc32.signed(buf) // -> -1805997238
|
|
||||||
crc32.unsigned(buf) // -> 2488970058
|
|
||||||
|
|
||||||
// will cast to buffer if given a string, so you can
|
|
||||||
// directly use foreign characters safely
|
|
||||||
crc32('自動販売機') // -> <Buffer cb 03 1a c5>
|
|
||||||
|
|
||||||
// and works in append mode too
|
|
||||||
var partialCrc = crc32('hey');
|
|
||||||
var partialCrc = crc32(' ', partialCrc);
|
|
||||||
var partialCrc = crc32('sup', partialCrc);
|
|
||||||
var partialCrc = crc32(' ', partialCrc);
|
|
||||||
var finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>
|
|
||||||
```
|
|
||||||
|
|
||||||
# tests
|
|
||||||
This was tested against the output of zlib's crc32 method. You can run
|
|
||||||
the tests with`npm test` (requires tap)
|
|
||||||
|
|
||||||
# see also
|
|
||||||
https://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also
|
|
||||||
supports buffer inputs and return unsigned ints (thanks @tjholowaychuk).
|
|
||||||
|
|
||||||
# license
|
|
||||||
MIT/X11
|
|
|
@ -1,91 +0,0 @@
|
||||||
var Buffer = require('buffer').Buffer;
|
|
||||||
|
|
||||||
var CRC_TABLE = [
|
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
|
||||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
|
||||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
|
||||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
|
||||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
|
||||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
|
||||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
|
||||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
|
||||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
|
||||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
|
||||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
|
||||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
|
||||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
|
||||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
|
||||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
|
||||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
|
||||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
|
||||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
|
||||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
|
||||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
|
||||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
|
||||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
|
||||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
|
||||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
|
||||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
|
||||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
|
||||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
|
||||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
|
||||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
|
||||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
|
||||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
|
||||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
|
||||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
|
||||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
|
||||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
|
||||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
|
||||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
|
||||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
|
||||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
|
||||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
|
||||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
|
||||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
|
||||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
|
||||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
|
||||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
|
||||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
|
||||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
|
||||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
|
||||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
|
||||||
0x2d02ef8d
|
|
||||||
];
|
|
||||||
|
|
||||||
if (typeof Int32Array !== 'undefined')
|
|
||||||
CRC_TABLE = new Int32Array(CRC_TABLE);
|
|
||||||
|
|
||||||
function bufferizeInt(num) {
|
|
||||||
var tmp = Buffer(4);
|
|
||||||
tmp.writeInt32BE(num, 0);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _crc32(buf, previous) {
|
|
||||||
if (!Buffer.isBuffer(buf)) {
|
|
||||||
buf = Buffer(buf);
|
|
||||||
}
|
|
||||||
if (Buffer.isBuffer(previous)) {
|
|
||||||
previous = previous.readUInt32BE(0);
|
|
||||||
}
|
|
||||||
var crc = ~~previous ^ -1;
|
|
||||||
for (var n = 0; n < buf.length; n++) {
|
|
||||||
crc = CRC_TABLE[(crc ^ buf[n]) & 0xff] ^ (crc >>> 8);
|
|
||||||
}
|
|
||||||
return (crc ^ -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function crc32() {
|
|
||||||
return bufferizeInt(_crc32.apply(null, arguments));
|
|
||||||
}
|
|
||||||
crc32.signed = function () {
|
|
||||||
return _crc32.apply(null, arguments);
|
|
||||||
};
|
|
||||||
crc32.unsigned = function () {
|
|
||||||
return _crc32.apply(null, arguments) >>> 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = crc32;
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"author": {
|
|
||||||
"name": "Brian J. Brennan",
|
|
||||||
"email": "brianloveswords@gmail.com",
|
|
||||||
"url": "http://bjb.io"
|
|
||||||
},
|
|
||||||
"name": "buffer-crc32",
|
|
||||||
"description": "A pure javascript CRC32 algorithm that plays nice with binary data",
|
|
||||||
"version": "0.2.3",
|
|
||||||
"contributors": [
|
|
||||||
{
|
|
||||||
"name": "Vladimir Kuznetsov"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"homepage": "https://github.com/brianloveswords/buffer-crc32",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/brianloveswords/buffer-crc32.git"
|
|
||||||
},
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "./node_modules/.bin/tap tests/*.test.js"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "~0.2.5"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"readme": "# buffer-crc32\n\n[![Build Status](https://secure.travis-ci.org/brianloveswords/buffer-crc32.png?branch=master)](http://travis-ci.org/brianloveswords/buffer-crc32)\n\ncrc32 that works with binary data and fancy character sets, outputs\nbuffer, signed or unsigned data and has tests.\n\nDerived from the sample CRC implementation in the PNG specification: http://www.w3.org/TR/PNG/#D-CRCAppendix\n\n# install\n```\nnpm install buffer-crc32\n```\n\n# example\n```js\nvar crc32 = require('buffer-crc32');\n// works with buffers\nvar buf = Buffer([0x00, 0x73, 0x75, 0x70, 0x20, 0x62, 0x72, 0x6f, 0x00])\ncrc32(buf) // -> <Buffer 94 5a ab 4a>\n\n// has convenience methods for getting signed or unsigned ints\ncrc32.signed(buf) // -> -1805997238\ncrc32.unsigned(buf) // -> 2488970058\n\n// will cast to buffer if given a string, so you can\n// directly use foreign characters safely\ncrc32('自動販売機') // -> <Buffer cb 03 1a c5>\n\n// and works in append mode too\nvar partialCrc = crc32('hey');\nvar partialCrc = crc32(' ', partialCrc);\nvar partialCrc = crc32('sup', partialCrc);\nvar partialCrc = crc32(' ', partialCrc);\nvar finalCrc = crc32('bros', partialCrc); // -> <Buffer 47 fa 55 70>\n```\n\n# tests\nThis was tested against the output of zlib's crc32 method. You can run\nthe tests with`npm test` (requires tap)\n\n# see also\nhttps://github.com/alexgorbatchev/node-crc, `crc.buffer.crc32` also\nsupports buffer inputs and return unsigned ints (thanks @tjholowaychuk).\n\n# license\nMIT/X11\n",
|
|
||||||
"readmeFilename": "README.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/brianloveswords/buffer-crc32/issues"
|
|
||||||
},
|
|
||||||
"_id": "buffer-crc32@0.2.3",
|
|
||||||
"_from": "buffer-crc32@0.2.3"
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
var crc32 = require('..');
|
|
||||||
var test = require('tap').test;
|
|
||||||
|
|
||||||
test('simple crc32 is no problem', function (t) {
|
|
||||||
var input = Buffer('hey sup bros');
|
|
||||||
var expected = Buffer([0x47, 0xfa, 0x55, 0x70]);
|
|
||||||
t.same(crc32(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('another simple one', function (t) {
|
|
||||||
var input = Buffer('IEND');
|
|
||||||
var expected = Buffer([0xae, 0x42, 0x60, 0x82]);
|
|
||||||
t.same(crc32(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('slightly more complex', function (t) {
|
|
||||||
var input = Buffer([0x00, 0x00, 0x00]);
|
|
||||||
var expected = Buffer([0xff, 0x41, 0xd9, 0x12]);
|
|
||||||
t.same(crc32(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('complex crc32 gets calculated like a champ', function (t) {
|
|
||||||
var input = Buffer('शीर्षक');
|
|
||||||
var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]);
|
|
||||||
t.same(crc32(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('casts to buffer if necessary', function (t) {
|
|
||||||
var input = 'शीर्षक';
|
|
||||||
var expected = Buffer([0x17, 0xb8, 0xaf, 0xf1]);
|
|
||||||
t.same(crc32(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('can do signed', function (t) {
|
|
||||||
var input = 'ham sandwich';
|
|
||||||
var expected = -1891873021;
|
|
||||||
t.same(crc32.signed(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('can do unsigned', function (t) {
|
|
||||||
var input = 'bear sandwich';
|
|
||||||
var expected = 3711466352;
|
|
||||||
t.same(crc32.unsigned(input), expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('simple crc32 in append mode', function (t) {
|
|
||||||
var input = [Buffer('hey'), Buffer(' '), Buffer('sup'), Buffer(' '), Buffer('bros')];
|
|
||||||
var expected = Buffer([0x47, 0xfa, 0x55, 0x70]);
|
|
||||||
for (var crc = 0, i = 0; i < input.length; i++) {
|
|
||||||
crc = crc32(input[i], crc);
|
|
||||||
}
|
|
||||||
t.same(crc, expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('can do signed in append mode', function (t) {
|
|
||||||
var input1 = 'ham';
|
|
||||||
var input2 = ' ';
|
|
||||||
var input3 = 'sandwich';
|
|
||||||
var expected = -1891873021;
|
|
||||||
|
|
||||||
var crc = crc32.signed(input1);
|
|
||||||
crc = crc32.signed(input2, crc);
|
|
||||||
crc = crc32.signed(input3, crc);
|
|
||||||
|
|
||||||
t.same(crc, expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('can do unsigned in append mode', function (t) {
|
|
||||||
var input1 = 'bear san';
|
|
||||||
var input2 = 'dwich';
|
|
||||||
var expected = 3711466352;
|
|
||||||
|
|
||||||
var crc = crc32.unsigned(input1);
|
|
||||||
crc = crc32.unsigned(input2, crc);
|
|
||||||
t.same(crc, expected);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
support
|
|
||||||
test
|
|
||||||
examples
|
|
||||||
*.sock
|
|
|
@ -1,27 +0,0 @@
|
||||||
1.0.4 / 2014-06-25
|
|
||||||
==================
|
|
||||||
|
|
||||||
* corrected avoidance of timing attacks (thanks @tenbits!)
|
|
||||||
|
|
||||||
|
|
||||||
1.0.3 / 2014-01-28
|
|
||||||
==================
|
|
||||||
|
|
||||||
* [incorrect] fix for timing attacks
|
|
||||||
|
|
||||||
1.0.2 / 2014-01-28
|
|
||||||
==================
|
|
||||||
|
|
||||||
* fix missing repository warning
|
|
||||||
* fix typo in test
|
|
||||||
|
|
||||||
1.0.1 / 2013-04-15
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Revert "Changed underlying HMAC algo. to sha512."
|
|
||||||
* Revert "Fix for timing attacks on MAC verification."
|
|
||||||
|
|
||||||
0.0.1 / 2010-01-03
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Initial release
|
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
test:
|
|
||||||
@./node_modules/.bin/mocha \
|
|
||||||
--require should \
|
|
||||||
--reporter spec
|
|
||||||
|
|
||||||
.PHONY: test
|
|
|
@ -1,42 +0,0 @@
|
||||||
|
|
||||||
# cookie-signature
|
|
||||||
|
|
||||||
Sign and unsign cookies.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```js
|
|
||||||
var cookie = require('cookie-signature');
|
|
||||||
|
|
||||||
var val = cookie.sign('hello', 'tobiiscool');
|
|
||||||
val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');
|
|
||||||
|
|
||||||
var val = cookie.sign('hello', 'tobiiscool');
|
|
||||||
cookie.unsign(val, 'tobiiscool').should.equal('hello');
|
|
||||||
cookie.unsign(val, 'luna').should.be.false;
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
(The MIT License)
|
|
||||||
|
|
||||||
Copyright (c) 2012 LearnBoost <tj@learnboost.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.
|
|
|
@ -1,51 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var crypto = require('crypto');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sign the given `val` with `secret`.
|
|
||||||
*
|
|
||||||
* @param {String} val
|
|
||||||
* @param {String} secret
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.sign = function(val, secret){
|
|
||||||
if ('string' != typeof val) throw new TypeError('cookie required');
|
|
||||||
if ('string' != typeof secret) throw new TypeError('secret required');
|
|
||||||
return val + '.' + crypto
|
|
||||||
.createHmac('sha256', secret)
|
|
||||||
.update(val)
|
|
||||||
.digest('base64')
|
|
||||||
.replace(/\=+$/, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsign and decode the given `val` with `secret`,
|
|
||||||
* returning `false` if the signature is invalid.
|
|
||||||
*
|
|
||||||
* @param {String} val
|
|
||||||
* @param {String} secret
|
|
||||||
* @return {String|Boolean}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.unsign = function(val, secret){
|
|
||||||
if ('string' != typeof val) throw new TypeError('cookie required');
|
|
||||||
if ('string' != typeof secret) throw new TypeError('secret required');
|
|
||||||
var str = val.slice(0, val.lastIndexOf('.'))
|
|
||||||
, mac = exports.sign(str, secret);
|
|
||||||
|
|
||||||
return sha1(mac) == sha1(val) ? str : false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function sha1(str){
|
|
||||||
return crypto.createHash('sha1').update(str).digest('hex');
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
{
|
|
||||||
"name": "cookie-signature",
|
|
||||||
"version": "1.0.4",
|
|
||||||
"description": "Sign and unsign cookies",
|
|
||||||
"keywords": [
|
|
||||||
"cookie",
|
|
||||||
"sign",
|
|
||||||
"unsign"
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "TJ Holowaychuk",
|
|
||||||
"email": "tj@learnboost.com"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/visionmedia/node-cookie-signature.git"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
|
||||||
"mocha": "*",
|
|
||||||
"should": "*"
|
|
||||||
},
|
|
||||||
"main": "index",
|
|
||||||
"readme": "\n# cookie-signature\n\n Sign and unsign cookies.\n\n## Example\n\n```js\nvar cookie = require('cookie-signature');\n\nvar val = cookie.sign('hello', 'tobiiscool');\nval.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');\n\nvar val = cookie.sign('hello', 'tobiiscool');\ncookie.unsign(val, 'tobiiscool').should.equal('hello');\ncookie.unsign(val, 'luna').should.be.false;\n```\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2012 LearnBoost <tj@learnboost.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
|
|
||||||
"readmeFilename": "Readme.md",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/visionmedia/node-cookie-signature/issues"
|
|
||||||
},
|
|
||||||
"_id": "cookie-signature@1.0.4",
|
|
||||||
"_from": "cookie-signature@1.0.4"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
test
|
|
||||||
.travis.yml
|
|
|
@ -1,9 +1,24 @@
|
||||||
// MIT License
|
(The MIT License)
|
||||||
|
|
||||||
Copyright (C) Roman Shtylman <shtylman@gmail.com>
|
Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com>
|
||||||
|
Copyright (c) 2015 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:
|
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 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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
|
@ -1,44 +1,317 @@
|
||||||
# cookie [![Build Status](https://secure.travis-ci.org/defunctzombie/node-cookie.png?branch=master)](http://travis-ci.org/defunctzombie/node-cookie) #
|
# cookie
|
||||||
|
|
||||||
cookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.
|
[![NPM Version][npm-version-image]][npm-url]
|
||||||
|
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||||
|
[![Node.js Version][node-image]][node-url]
|
||||||
|
[![Build Status][ci-image]][ci-url]
|
||||||
|
[![Coverage Status][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
See [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.
|
Basic HTTP cookie parser and serializer for HTTP servers.
|
||||||
|
|
||||||
## how?
|
## Installation
|
||||||
|
|
||||||
```
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
npm install cookie
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install cookie
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
## API
|
||||||
|
|
||||||
|
```js
|
||||||
var cookie = require('cookie');
|
var cookie = require('cookie');
|
||||||
|
|
||||||
var hdr = cookie.serialize('foo', 'bar');
|
|
||||||
// hdr = 'foo=bar';
|
|
||||||
|
|
||||||
var cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');
|
|
||||||
// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## more
|
### cookie.parse(str, options)
|
||||||
|
|
||||||
The serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.
|
Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs.
|
||||||
|
The `str` argument is the string representing a `Cookie` header value and `options` is an
|
||||||
|
optional object containing additional parsing options.
|
||||||
|
|
||||||
### path
|
```js
|
||||||
> cookie path
|
var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2');
|
||||||
|
// { foo: 'bar', equation: 'E=mc^2' }
|
||||||
|
```
|
||||||
|
|
||||||
### expires
|
#### Options
|
||||||
> absolute expiration date for the cookie (Date object)
|
|
||||||
|
|
||||||
### maxAge
|
`cookie.parse` accepts these properties in the options object.
|
||||||
> relative max age of the cookie from when the client receives it (seconds)
|
|
||||||
|
|
||||||
### domain
|
##### decode
|
||||||
> domain for the cookie
|
|
||||||
|
|
||||||
### secure
|
Specifies a function that will be used to decode a cookie's value. Since the value of a cookie
|
||||||
> true or false
|
has a limited character set (and must be a simple string), this function can be used to decode
|
||||||
|
a previously-encoded cookie value into a JavaScript string or other object.
|
||||||
|
|
||||||
### httpOnly
|
The default function is the global `decodeURIComponent`, which will decode any URL-encoded
|
||||||
> true or false
|
sequences into their byte representations.
|
||||||
|
|
||||||
|
**note** if an error is thrown from this function, the original, non-decoded cookie value will
|
||||||
|
be returned as the cookie's value.
|
||||||
|
|
||||||
|
### cookie.serialize(name, value, options)
|
||||||
|
|
||||||
|
Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the
|
||||||
|
name for the cookie, the `value` argument is the value to set the cookie to, and the `options`
|
||||||
|
argument is an optional object containing additional serialization options.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var setCookie = cookie.serialize('foo', 'bar');
|
||||||
|
// foo=bar
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
`cookie.serialize` accepts these properties in the options object.
|
||||||
|
|
||||||
|
##### domain
|
||||||
|
|
||||||
|
Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no
|
||||||
|
domain is set, and most clients will consider the cookie to apply to only the current domain.
|
||||||
|
|
||||||
|
##### encode
|
||||||
|
|
||||||
|
Specifies a function that will be used to encode a cookie's value. Since value of a cookie
|
||||||
|
has a limited character set (and must be a simple string), this function can be used to encode
|
||||||
|
a value into a string suited for a cookie's value.
|
||||||
|
|
||||||
|
The default function is the global `encodeURIComponent`, which will encode a JavaScript string
|
||||||
|
into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range.
|
||||||
|
|
||||||
|
##### expires
|
||||||
|
|
||||||
|
Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1].
|
||||||
|
By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and
|
||||||
|
will delete it on a condition like exiting a web browser application.
|
||||||
|
|
||||||
|
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
|
||||||
|
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||||
|
so if both are set, they should point to the same date and time.
|
||||||
|
|
||||||
|
##### httpOnly
|
||||||
|
|
||||||
|
Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy,
|
||||||
|
the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set.
|
||||||
|
|
||||||
|
**note** be careful when setting this to `true`, as compliant clients will not allow client-side
|
||||||
|
JavaScript to see the cookie in `document.cookie`.
|
||||||
|
|
||||||
|
##### maxAge
|
||||||
|
|
||||||
|
Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2].
|
||||||
|
The given number will be converted to an integer by rounding down. By default, no maximum age is set.
|
||||||
|
|
||||||
|
**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
|
||||||
|
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||||
|
so if both are set, they should point to the same date and time.
|
||||||
|
|
||||||
|
##### partitioned
|
||||||
|
|
||||||
|
Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
|
||||||
|
attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the
|
||||||
|
`Partitioned` attribute is not set.
|
||||||
|
|
||||||
|
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||||
|
This also means many clients may ignore this attribute until they understand it.
|
||||||
|
|
||||||
|
More information about can be found in [the proposal](https://github.com/privacycg/CHIPS).
|
||||||
|
|
||||||
|
##### path
|
||||||
|
|
||||||
|
Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path
|
||||||
|
is considered the ["default path"][rfc-6265-5.1.4].
|
||||||
|
|
||||||
|
##### priority
|
||||||
|
|
||||||
|
Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
|
||||||
|
|
||||||
|
- `'low'` will set the `Priority` attribute to `Low`.
|
||||||
|
- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
||||||
|
- `'high'` will set the `Priority` attribute to `High`.
|
||||||
|
|
||||||
|
More information about the different priority levels can be found in
|
||||||
|
[the specification][rfc-west-cookie-priority-00-4.1].
|
||||||
|
|
||||||
|
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||||
|
This also means many clients may ignore this attribute until they understand it.
|
||||||
|
|
||||||
|
##### sameSite
|
||||||
|
|
||||||
|
Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-09-5.4.7].
|
||||||
|
|
||||||
|
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||||
|
- `false` will not set the `SameSite` attribute.
|
||||||
|
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
||||||
|
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
||||||
|
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||||
|
|
||||||
|
More information about the different enforcement levels can be found in
|
||||||
|
[the specification][rfc-6265bis-09-5.4.7].
|
||||||
|
|
||||||
|
**note** This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||||
|
This also means many clients may ignore this attribute until they understand it.
|
||||||
|
|
||||||
|
##### secure
|
||||||
|
|
||||||
|
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy,
|
||||||
|
the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
|
||||||
|
|
||||||
|
**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to
|
||||||
|
the server in the future if the browser does not have an HTTPS connection.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The following example uses this module in conjunction with the Node.js core HTTP server
|
||||||
|
to prompt a user for their name and display it back on future visits.
|
||||||
|
|
||||||
|
```js
|
||||||
|
var cookie = require('cookie');
|
||||||
|
var escapeHtml = require('escape-html');
|
||||||
|
var http = require('http');
|
||||||
|
var url = require('url');
|
||||||
|
|
||||||
|
function onRequest(req, res) {
|
||||||
|
// Parse the query string
|
||||||
|
var query = url.parse(req.url, true, true).query;
|
||||||
|
|
||||||
|
if (query && query.name) {
|
||||||
|
// Set a new cookie with the name
|
||||||
|
res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), {
|
||||||
|
httpOnly: true,
|
||||||
|
maxAge: 60 * 60 * 24 * 7 // 1 week
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Redirect back after setting cookie
|
||||||
|
res.statusCode = 302;
|
||||||
|
res.setHeader('Location', req.headers.referer || '/');
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the cookies on the request
|
||||||
|
var cookies = cookie.parse(req.headers.cookie || '');
|
||||||
|
|
||||||
|
// Get the visitor name set in the cookie
|
||||||
|
var name = cookies.name;
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>');
|
||||||
|
} else {
|
||||||
|
res.write('<p>Hello, new visitor!</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
res.write('<form method="GET">');
|
||||||
|
res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">');
|
||||||
|
res.end('</form>');
|
||||||
|
}
|
||||||
|
|
||||||
|
http.createServer(onRequest).listen(3000);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benchmark
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm run bench
|
||||||
|
|
||||||
|
> cookie@0.5.0 bench
|
||||||
|
> node benchmark/index.js
|
||||||
|
|
||||||
|
node@18.18.2
|
||||||
|
acorn@8.10.0
|
||||||
|
ada@2.6.0
|
||||||
|
ares@1.19.1
|
||||||
|
brotli@1.0.9
|
||||||
|
cldr@43.1
|
||||||
|
icu@73.2
|
||||||
|
llhttp@6.0.11
|
||||||
|
modules@108
|
||||||
|
napi@9
|
||||||
|
nghttp2@1.57.0
|
||||||
|
nghttp3@0.7.0
|
||||||
|
ngtcp2@0.8.1
|
||||||
|
openssl@3.0.10+quic
|
||||||
|
simdutf@3.2.14
|
||||||
|
tz@2023c
|
||||||
|
undici@5.26.3
|
||||||
|
unicode@15.0
|
||||||
|
uv@1.44.2
|
||||||
|
uvwasi@0.0.18
|
||||||
|
v8@10.2.154.26-node.26
|
||||||
|
zlib@1.2.13.1-motley
|
||||||
|
|
||||||
|
> node benchmark/parse-top.js
|
||||||
|
|
||||||
|
cookie.parse - top sites
|
||||||
|
|
||||||
|
14 tests completed.
|
||||||
|
|
||||||
|
parse accounts.google.com x 2,588,913 ops/sec ±0.74% (186 runs sampled)
|
||||||
|
parse apple.com x 2,370,002 ops/sec ±0.69% (186 runs sampled)
|
||||||
|
parse cloudflare.com x 2,213,102 ops/sec ±0.88% (188 runs sampled)
|
||||||
|
parse docs.google.com x 2,194,157 ops/sec ±1.03% (184 runs sampled)
|
||||||
|
parse drive.google.com x 2,265,084 ops/sec ±0.79% (187 runs sampled)
|
||||||
|
parse en.wikipedia.org x 457,099 ops/sec ±0.81% (186 runs sampled)
|
||||||
|
parse linkedin.com x 504,407 ops/sec ±0.89% (186 runs sampled)
|
||||||
|
parse maps.google.com x 1,230,959 ops/sec ±0.98% (186 runs sampled)
|
||||||
|
parse microsoft.com x 926,294 ops/sec ±0.88% (184 runs sampled)
|
||||||
|
parse play.google.com x 2,311,338 ops/sec ±0.83% (185 runs sampled)
|
||||||
|
parse support.google.com x 1,508,850 ops/sec ±0.86% (186 runs sampled)
|
||||||
|
parse www.google.com x 1,022,582 ops/sec ±1.32% (182 runs sampled)
|
||||||
|
parse youtu.be x 332,136 ops/sec ±1.02% (185 runs sampled)
|
||||||
|
parse youtube.com x 323,833 ops/sec ±0.77% (183 runs sampled)
|
||||||
|
|
||||||
|
> node benchmark/parse.js
|
||||||
|
|
||||||
|
cookie.parse - generic
|
||||||
|
|
||||||
|
6 tests completed.
|
||||||
|
|
||||||
|
simple x 3,214,032 ops/sec ±1.61% (183 runs sampled)
|
||||||
|
decode x 587,237 ops/sec ±1.16% (187 runs sampled)
|
||||||
|
unquote x 2,954,618 ops/sec ±1.35% (183 runs sampled)
|
||||||
|
duplicates x 857,008 ops/sec ±0.89% (187 runs sampled)
|
||||||
|
10 cookies x 292,133 ops/sec ±0.89% (187 runs sampled)
|
||||||
|
100 cookies x 22,610 ops/sec ±0.68% (187 runs sampled)
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [RFC 6265: HTTP State Management Mechanism][rfc-6265]
|
||||||
|
- [Same-site Cookies][rfc-6265bis-09-5.4.7]
|
||||||
|
|
||||||
|
[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/
|
||||||
|
[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1
|
||||||
|
[rfc-6265bis-09-5.4.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7
|
||||||
|
[rfc-6265]: https://tools.ietf.org/html/rfc6265
|
||||||
|
[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4
|
||||||
|
[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1
|
||||||
|
[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2
|
||||||
|
[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3
|
||||||
|
[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4
|
||||||
|
[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5
|
||||||
|
[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6
|
||||||
|
[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
|
|
||||||
|
[ci-image]: https://badgen.net/github/checks/jshttp/cookie/master?label=ci
|
||||||
|
[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml
|
||||||
|
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master
|
||||||
|
[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
|
||||||
|
[node-image]: https://badgen.net/npm/node/cookie
|
||||||
|
[node-url]: https://nodejs.org/en/download
|
||||||
|
[npm-downloads-image]: https://badgen.net/npm/dm/cookie
|
||||||
|
[npm-url]: https://npmjs.org/package/cookie
|
||||||
|
[npm-version-image]: https://badgen.net/npm/v/cookie
|
||||||
|
|
|
@ -1,75 +1,274 @@
|
||||||
|
/*!
|
||||||
|
* cookie
|
||||||
|
* Copyright(c) 2012-2014 Roman Shtylman
|
||||||
|
* Copyright(c) 2015 Douglas Christopher Wilson
|
||||||
|
* MIT Licensed
|
||||||
|
*/
|
||||||
|
|
||||||
/// Serialize the a name value pair into a cookie string suitable for
|
'use strict';
|
||||||
/// http headers. An optional options object specified cookie parameters
|
|
||||||
///
|
|
||||||
/// serialize('foo', 'bar', { httpOnly: true })
|
|
||||||
/// => "foo=bar; httpOnly"
|
|
||||||
///
|
|
||||||
/// @param {String} name
|
|
||||||
/// @param {String} val
|
|
||||||
/// @param {Object} options
|
|
||||||
/// @return {String}
|
|
||||||
var serialize = function(name, val, opt){
|
|
||||||
opt = opt || {};
|
|
||||||
var enc = opt.encode || encode;
|
|
||||||
var pairs = [name + '=' + enc(val)];
|
|
||||||
|
|
||||||
if (null != opt.maxAge) {
|
/**
|
||||||
var maxAge = opt.maxAge - 0;
|
* Module exports.
|
||||||
if (isNaN(maxAge)) throw new Error('maxAge should be a Number');
|
* @public
|
||||||
pairs.push('Max-Age=' + maxAge);
|
*/
|
||||||
|
|
||||||
|
exports.parse = parse;
|
||||||
|
exports.serialize = serialize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module variables.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
var __toString = Object.prototype.toString
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RegExp to match field-content in RFC 7230 sec 3.2
|
||||||
|
*
|
||||||
|
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||||||
|
* field-vchar = VCHAR / obs-text
|
||||||
|
* obs-text = %x80-FF
|
||||||
|
*/
|
||||||
|
|
||||||
|
var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a cookie header.
|
||||||
|
*
|
||||||
|
* Parse the given cookie header string into an object
|
||||||
|
* The object has the various cookies as keys(names) => values
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {object}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parse(str, options) {
|
||||||
|
if (typeof str !== 'string') {
|
||||||
|
throw new TypeError('argument str must be a string');
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj = {}
|
||||||
|
var opt = options || {};
|
||||||
|
var dec = opt.decode || decode;
|
||||||
|
|
||||||
|
var index = 0
|
||||||
|
while (index < str.length) {
|
||||||
|
var eqIdx = str.indexOf('=', index)
|
||||||
|
|
||||||
|
// no more cookie pairs
|
||||||
|
if (eqIdx === -1) {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.domain) pairs.push('Domain=' + opt.domain);
|
var endIdx = str.indexOf(';', index)
|
||||||
if (opt.path) pairs.push('Path=' + opt.path);
|
|
||||||
if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString());
|
|
||||||
if (opt.httpOnly) pairs.push('HttpOnly');
|
|
||||||
if (opt.secure) pairs.push('Secure');
|
|
||||||
|
|
||||||
return pairs.join('; ');
|
if (endIdx === -1) {
|
||||||
};
|
endIdx = str.length
|
||||||
|
} else if (endIdx < eqIdx) {
|
||||||
|
// backtrack on prior semicolon
|
||||||
|
index = str.lastIndexOf(';', eqIdx - 1) + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse the given cookie header string into an object
|
var key = str.slice(index, eqIdx).trim()
|
||||||
/// The object has the various cookies as keys(names) => values
|
|
||||||
/// @param {String} str
|
|
||||||
/// @return {Object}
|
|
||||||
var parse = function(str, opt) {
|
|
||||||
opt = opt || {};
|
|
||||||
var obj = {}
|
|
||||||
var pairs = str.split(/; */);
|
|
||||||
var dec = opt.decode || decode;
|
|
||||||
|
|
||||||
pairs.forEach(function(pair) {
|
// only assign once
|
||||||
var eq_idx = pair.indexOf('=')
|
if (undefined === obj[key]) {
|
||||||
|
var val = str.slice(eqIdx + 1, endIdx).trim()
|
||||||
|
|
||||||
// skip things that don't look like key=value
|
// quoted values
|
||||||
if (eq_idx < 0) {
|
if (val.charCodeAt(0) === 0x22) {
|
||||||
return;
|
val = val.slice(1, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = pair.substr(0, eq_idx).trim()
|
obj[key] = tryDecode(val, dec);
|
||||||
var val = pair.substr(++eq_idx, pair.length).trim();
|
}
|
||||||
|
|
||||||
// quoted values
|
index = endIdx + 1
|
||||||
if ('"' == val[0]) {
|
}
|
||||||
val = val.slice(1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// only assign once
|
return obj;
|
||||||
if (undefined == obj[key]) {
|
}
|
||||||
try {
|
|
||||||
obj[key] = dec(val);
|
|
||||||
} catch (e) {
|
|
||||||
obj[key] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
/**
|
||||||
};
|
* Serialize data into a cookie header.
|
||||||
|
*
|
||||||
|
* Serialize the a name value pair into a cookie string suitable for
|
||||||
|
* http headers. An optional options object specified cookie parameters.
|
||||||
|
*
|
||||||
|
* serialize('foo', 'bar', { httpOnly: true })
|
||||||
|
* => "foo=bar; httpOnly"
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @param {string} val
|
||||||
|
* @param {object} [options]
|
||||||
|
* @return {string}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
|
||||||
var encode = encodeURIComponent;
|
function serialize(name, val, options) {
|
||||||
var decode = decodeURIComponent;
|
var opt = options || {};
|
||||||
|
var enc = opt.encode || encode;
|
||||||
|
|
||||||
module.exports.serialize = serialize;
|
if (typeof enc !== 'function') {
|
||||||
module.exports.parse = parse;
|
throw new TypeError('option encode is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fieldContentRegExp.test(name)) {
|
||||||
|
throw new TypeError('argument name is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = enc(val);
|
||||||
|
|
||||||
|
if (value && !fieldContentRegExp.test(value)) {
|
||||||
|
throw new TypeError('argument val is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
var str = name + '=' + value;
|
||||||
|
|
||||||
|
if (null != opt.maxAge) {
|
||||||
|
var maxAge = opt.maxAge - 0;
|
||||||
|
|
||||||
|
if (isNaN(maxAge) || !isFinite(maxAge)) {
|
||||||
|
throw new TypeError('option maxAge is invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '; Max-Age=' + Math.floor(maxAge);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.domain) {
|
||||||
|
if (!fieldContentRegExp.test(opt.domain)) {
|
||||||
|
throw new TypeError('option domain is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '; Domain=' + opt.domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.path) {
|
||||||
|
if (!fieldContentRegExp.test(opt.path)) {
|
||||||
|
throw new TypeError('option path is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '; Path=' + opt.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.expires) {
|
||||||
|
var expires = opt.expires
|
||||||
|
|
||||||
|
if (!isDate(expires) || isNaN(expires.valueOf())) {
|
||||||
|
throw new TypeError('option expires is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
str += '; Expires=' + expires.toUTCString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.httpOnly) {
|
||||||
|
str += '; HttpOnly';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.secure) {
|
||||||
|
str += '; Secure';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.partitioned) {
|
||||||
|
str += '; Partitioned'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.priority) {
|
||||||
|
var priority = typeof opt.priority === 'string'
|
||||||
|
? opt.priority.toLowerCase()
|
||||||
|
: opt.priority
|
||||||
|
|
||||||
|
switch (priority) {
|
||||||
|
case 'low':
|
||||||
|
str += '; Priority=Low'
|
||||||
|
break
|
||||||
|
case 'medium':
|
||||||
|
str += '; Priority=Medium'
|
||||||
|
break
|
||||||
|
case 'high':
|
||||||
|
str += '; Priority=High'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new TypeError('option priority is invalid')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.sameSite) {
|
||||||
|
var sameSite = typeof opt.sameSite === 'string'
|
||||||
|
? opt.sameSite.toLowerCase() : opt.sameSite;
|
||||||
|
|
||||||
|
switch (sameSite) {
|
||||||
|
case true:
|
||||||
|
str += '; SameSite=Strict';
|
||||||
|
break;
|
||||||
|
case 'lax':
|
||||||
|
str += '; SameSite=Lax';
|
||||||
|
break;
|
||||||
|
case 'strict':
|
||||||
|
str += '; SameSite=Strict';
|
||||||
|
break;
|
||||||
|
case 'none':
|
||||||
|
str += '; SameSite=None';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new TypeError('option sameSite is invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL-decode string value. Optimized to skip native call when no %.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function decode (str) {
|
||||||
|
return str.indexOf('%') !== -1
|
||||||
|
? decodeURIComponent(str)
|
||||||
|
: str
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL-encode value.
|
||||||
|
*
|
||||||
|
* @param {string} val
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function encode (val) {
|
||||||
|
return encodeURIComponent(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if value is a Date.
|
||||||
|
*
|
||||||
|
* @param {*} val
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isDate (val) {
|
||||||
|
return __toString.call(val) === '[object Date]' ||
|
||||||
|
val instanceof Date
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try decoding a string using a decoding function.
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
* @param {function} decode
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function tryDecode(str, decode) {
|
||||||
|
try {
|
||||||
|
return decode(str);
|
||||||
|
} catch (e) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,36 +1,44 @@
|
||||||
{
|
{
|
||||||
"author": {
|
|
||||||
"name": "Roman Shtylman",
|
|
||||||
"email": "shtylman@gmail.com"
|
|
||||||
},
|
|
||||||
"name": "cookie",
|
"name": "cookie",
|
||||||
"description": "cookie parsing and serialization",
|
"description": "HTTP server cookie parsing and serialization",
|
||||||
"version": "0.1.2",
|
"version": "0.6.0",
|
||||||
"repository": {
|
"author": "Roman Shtylman <shtylman@gmail.com>",
|
||||||
"type": "git",
|
"contributors": [
|
||||||
"url": "git://github.com/shtylman/node-cookie.git"
|
"Douglas Christopher Wilson <doug@somethingdoug.com>"
|
||||||
},
|
],
|
||||||
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"cookie",
|
"cookie",
|
||||||
"cookies"
|
"cookies"
|
||||||
],
|
],
|
||||||
"main": "index.js",
|
"repository": "jshttp/cookie",
|
||||||
"scripts": {
|
|
||||||
"test": "mocha"
|
|
||||||
},
|
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "1.x.x"
|
"beautify-benchmark": "0.2.4",
|
||||||
|
"benchmark": "2.1.4",
|
||||||
|
"eslint": "8.53.0",
|
||||||
|
"eslint-plugin-markdown": "3.0.1",
|
||||||
|
"mocha": "10.2.0",
|
||||||
|
"nyc": "15.1.0",
|
||||||
|
"safe-buffer": "5.2.1",
|
||||||
|
"top-sites": "1.1.194"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {},
|
"files": [
|
||||||
|
"HISTORY.md",
|
||||||
|
"LICENSE",
|
||||||
|
"README.md",
|
||||||
|
"SECURITY.md",
|
||||||
|
"index.js"
|
||||||
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": ">= 0.6"
|
||||||
},
|
},
|
||||||
"readme": "# cookie [![Build Status](https://secure.travis-ci.org/defunctzombie/node-cookie.png?branch=master)](http://travis-ci.org/defunctzombie/node-cookie) #\n\ncookie is a basic cookie parser and serializer. It doesn't make assumptions about how you are going to deal with your cookies. It basically just provides a way to read and write the HTTP cookie headers.\n\nSee [RFC6265](http://tools.ietf.org/html/rfc6265) for details about the http header for cookies.\n\n## how?\n\n```\nnpm install cookie\n```\n\n```javascript\nvar cookie = require('cookie');\n\nvar hdr = cookie.serialize('foo', 'bar');\n// hdr = 'foo=bar';\n\nvar cookies = cookie.parse('foo=bar; cat=meow; dog=ruff');\n// cookies = { foo: 'bar', cat: 'meow', dog: 'ruff' };\n```\n\n## more\n\nThe serialize function takes a third parameter, an object, to set cookie options. See the RFC for valid values.\n\n### path\n> cookie path\n\n### expires\n> absolute expiration date for the cookie (Date object)\n\n### maxAge\n> relative max age of the cookie from when the client receives it (seconds)\n\n### domain\n> domain for the cookie\n\n### secure\n> true or false\n\n### httpOnly\n> true or false\n\n",
|
"scripts": {
|
||||||
"readmeFilename": "README.md",
|
"bench": "node benchmark/index.js",
|
||||||
"bugs": {
|
"lint": "eslint .",
|
||||||
"url": "https://github.com/shtylman/node-cookie/issues"
|
"test": "mocha --reporter spec --bail --check-leaks test/",
|
||||||
},
|
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
|
||||||
"_id": "cookie@0.1.2",
|
"test-cov": "nyc --reporter=html --reporter=text npm test",
|
||||||
"_from": "cookie@0.1.2"
|
"update-bench": "node scripts/update-benchmark.js",
|
||||||
|
"version": "node scripts/version-history.js && git add HISTORY.md"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"laxbreak": true
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue