mirror of https://gitee.com/bigwinds/arangodb
Removed unused deps.
This commit is contained in:
parent
469d73c8b8
commit
d6a46773cd
|
@ -33,8 +33,6 @@ var internal = require('internal');
|
|||
var Buffer = require('buffer').Buffer;
|
||||
var extend = require('underscore').extend;
|
||||
var is = require('org/arangodb/is');
|
||||
var mediaTyper = require('media-typer');
|
||||
var contentDisposition = require('content-disposition');
|
||||
var querystring = require('querystring');
|
||||
var qs = require('qs');
|
||||
var url = require('url');
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
0.5.0 / 2014-10-11
|
||||
==================
|
||||
|
||||
* Add `parse` function
|
||||
|
||||
0.4.0 / 2014-09-21
|
||||
==================
|
||||
|
||||
* Expand non-Unicode `filename` to the full ISO-8859-1 charset
|
||||
|
||||
0.3.0 / 2014-09-20
|
||||
==================
|
||||
|
||||
* Add `fallback` option
|
||||
* Add `type` option
|
||||
|
||||
0.2.0 / 2014-09-19
|
||||
==================
|
||||
|
||||
* Reduce ambiguity of file names with hex escape in buggy browsers
|
||||
|
||||
0.1.2 / 2014-09-19
|
||||
==================
|
||||
|
||||
* Fix periodic invalid Unicode filename header
|
||||
|
||||
0.1.1 / 2014-09-19
|
||||
==================
|
||||
|
||||
* Fix invalid characters appearing in `filename*` parameter
|
||||
|
||||
0.1.0 / 2014-09-18
|
||||
==================
|
||||
|
||||
* Make the `filename` argument optional
|
||||
|
||||
0.0.0 / 2014-09-18
|
||||
==================
|
||||
|
||||
* Initial release
|
|
@ -1,22 +0,0 @@
|
|||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Douglas Christopher Wilson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,141 +0,0 @@
|
|||
# content-disposition
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
Create and parse HTTP `Content-Disposition` header
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ npm install content-disposition
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var contentDisposition = require('content-disposition')
|
||||
```
|
||||
|
||||
### contentDisposition(filename, options)
|
||||
|
||||
Create an attachment `Content-Disposition` header value using the given file name,
|
||||
if supplied. The `filename` is optional and if no file name is desired, but you
|
||||
want to specify `options`, set `filename` to `undefined`.
|
||||
|
||||
```js
|
||||
res.setHeader('Content-Disposition', contentDisposition('∫ maths.pdf'))
|
||||
```
|
||||
|
||||
**note** HTTP headers are of the ISO-8859-1 character set. If you are writing this
|
||||
header through a means different from `setHeader` in Node.js, you'll want to specify
|
||||
the `'binary'` encoding in Node.js.
|
||||
|
||||
#### Options
|
||||
|
||||
`contentDisposition` accepts these properties in the options object.
|
||||
|
||||
##### fallback
|
||||
|
||||
If the `filename` option is outside ISO-8859-1, then the file name is actually
|
||||
stored in a supplemental field for clients that support Unicode file names and
|
||||
a ISO-8859-1 version of the file name is automatically generated.
|
||||
|
||||
This specifies the ISO-8859-1 file name to override the automatic generation or
|
||||
disables the generation all together, defaults to `true`.
|
||||
|
||||
- A string will specify the ISO-8859-1 file name to use in place of automatic
|
||||
generation.
|
||||
- `false` will disable including a ISO-8859-1 file name and only include the
|
||||
Unicode version (unless the file name is already ISO-8859-1).
|
||||
- `true` will enable automatic generation if the file name is outside ISO-8859-1.
|
||||
|
||||
If the `filename` option is ISO-8859-1 and this option is specified and has a
|
||||
different value, then the `filename` option is encoded in the extended field
|
||||
and this set as the fallback field, even though they are both ISO-8859-1.
|
||||
|
||||
##### type
|
||||
|
||||
Specifies the disposition type, defaults to `"attachment"`. This can also be
|
||||
`"inline"`, or any other value (all values except inline are treated like
|
||||
`attachment`, but can convey additional information if both parties agree to
|
||||
it). The type is normalized to lower-case.
|
||||
|
||||
### contentDisposition.parse(string)
|
||||
|
||||
```js
|
||||
var disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt"');
|
||||
```
|
||||
|
||||
Parse a `Content-Disposition` header string. This automatically handles extended
|
||||
("Unicode") parameters by decoding them and providing them under the standard
|
||||
parameter name. This will return an object with the following properties (examples
|
||||
are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt'`):
|
||||
|
||||
- `type`: The disposition type (always lower case). Example: `'attachment'`
|
||||
|
||||
- `parameters`: An object of the parameters in the disposition (name of parameter
|
||||
always lower case and extended versions replace non-extended versions). Example:
|
||||
`{filename: "€ rates.txt"}`
|
||||
|
||||
## Examples
|
||||
|
||||
### Send a file for download
|
||||
|
||||
```js
|
||||
var contentDisposition = require('content-disposition')
|
||||
var destroy = require('destroy')
|
||||
var http = require('http')
|
||||
var onFinished = require('on-finished')
|
||||
|
||||
var filePath = '/path/to/public/plans.pdf'
|
||||
|
||||
http.createServer(function onRequest(req, res) {
|
||||
// set headers
|
||||
res.setHeader('Content-Type', 'application/pdf')
|
||||
res.setHeader('Content-Disposition', contentDisposition(filePath))
|
||||
|
||||
// send file
|
||||
var stream = fs.createReadStream(filePath)
|
||||
stream.pipe(res)
|
||||
onFinished(res, function (err) {
|
||||
destroy(stream)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1][rfc-2616]
|
||||
- [RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters][rfc-5987]
|
||||
- [RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)][rfc-6266]
|
||||
- [Test Cases for HTTP Content-Disposition header field (RFC 6266) and the Encodings defined in RFCs 2047, 2231 and 5987][tc-2231]
|
||||
|
||||
[rfc-2616]: https://tools.ietf.org/html/rfc2616
|
||||
[rfc-5987]: https://tools.ietf.org/html/rfc5987
|
||||
[rfc-6266]: https://tools.ietf.org/html/rfc6266
|
||||
[tc-2231]: http://greenbytes.de/tech/tc2231/
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/content-disposition.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/content-disposition
|
||||
[node-version-image]: https://img.shields.io/node/v/content-disposition.svg?style=flat
|
||||
[node-version-url]: http://nodejs.org/download/
|
||||
[travis-image]: https://img.shields.io/travis/jshttp/content-disposition.svg?style=flat
|
||||
[travis-url]: https://travis-ci.org/jshttp/content-disposition
|
||||
[coveralls-image]: https://img.shields.io/coveralls/jshttp/content-disposition.svg?style=flat
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/content-disposition.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/content-disposition
|
|
@ -1,443 +0,0 @@
|
|||
/*!
|
||||
* content-disposition
|
||||
* Copyright(c) 2014 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = contentDisposition
|
||||
module.exports.parse = parse
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var basename = require('path').basename
|
||||
|
||||
/**
|
||||
* RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%")
|
||||
*/
|
||||
|
||||
var encodeUriAttrCharRegExp = /[\x00-\x20"'\(\)*,\/:;<=>?@\[\\\]\{\}\x7f]/g
|
||||
|
||||
/**
|
||||
* RegExp to match percent encoding escape.
|
||||
*/
|
||||
|
||||
var hexEscapeRegExp = /%[0-9A-Fa-f]{2}/
|
||||
var hexEscapeReplaceRegExp = /%([0-9A-Fa-f]{2})/g
|
||||
|
||||
/**
|
||||
* RegExp to match non-latin1 characters.
|
||||
*/
|
||||
|
||||
var nonLatin1RegExp = /[^\x20-\x7e\xa0-\xff]/g
|
||||
|
||||
/**
|
||||
* RegExp to match quoted-pair in RFC 2616
|
||||
*
|
||||
* quoted-pair = "\" CHAR
|
||||
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
*/
|
||||
|
||||
var qescRegExp = /\\([\u0000-\u007f])/g;
|
||||
|
||||
/**
|
||||
* RegExp to match chars that must be quoted-pair in RFC 2616
|
||||
*/
|
||||
|
||||
var quoteRegExp = /([\\"])/g
|
||||
|
||||
/**
|
||||
* RegExp for various RFC 2616 grammar
|
||||
*
|
||||
* parameter = token "=" ( token | quoted-string )
|
||||
* token = 1*<any CHAR except CTLs or separators>
|
||||
* separators = "(" | ")" | "<" | ">" | "@"
|
||||
* | "," | ";" | ":" | "\" | <">
|
||||
* | "/" | "[" | "]" | "?" | "="
|
||||
* | "{" | "}" | SP | HT
|
||||
* quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
|
||||
* qdtext = <any TEXT except <">>
|
||||
* quoted-pair = "\" CHAR
|
||||
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
* TEXT = <any OCTET except CTLs, but including LWS>
|
||||
* LWS = [CRLF] 1*( SP | HT )
|
||||
* CRLF = CR LF
|
||||
* CR = <US-ASCII CR, carriage return (13)>
|
||||
* LF = <US-ASCII LF, linefeed (10)>
|
||||
* SP = <US-ASCII SP, space (32)>
|
||||
* HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
||||
* OCTET = <any 8-bit sequence of data>
|
||||
*/
|
||||
|
||||
var paramRegExp = /; *([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *= *("(?:[ !\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) */g
|
||||
var textRegExp = /^[\x20-\x7e\x80-\xff]+$/
|
||||
var tokenRegExp = /^[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+$/
|
||||
|
||||
/**
|
||||
* RegExp for various RFC 5987 grammar
|
||||
*
|
||||
* ext-value = charset "'" [ language ] "'" value-chars
|
||||
* charset = "UTF-8" / "ISO-8859-1" / mime-charset
|
||||
* mime-charset = 1*mime-charsetc
|
||||
* mime-charsetc = ALPHA / DIGIT
|
||||
* / "!" / "#" / "$" / "%" / "&"
|
||||
* / "+" / "-" / "^" / "_" / "`"
|
||||
* / "{" / "}" / "~"
|
||||
* language = ( 2*3ALPHA [ extlang ] )
|
||||
* / 4ALPHA
|
||||
* / 5*8ALPHA
|
||||
* extlang = *3( "-" 3ALPHA )
|
||||
* value-chars = *( pct-encoded / attr-char )
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
* attr-char = ALPHA / DIGIT
|
||||
* / "!" / "#" / "$" / "&" / "+" / "-" / "."
|
||||
* / "^" / "_" / "`" / "|" / "~"
|
||||
*/
|
||||
|
||||
var extValueRegExp = /^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+\-\.^_`|~])+)$/
|
||||
|
||||
/**
|
||||
* RegExp for various RFC 6266 grammar
|
||||
*
|
||||
* disposition-type = "inline" | "attachment" | disp-ext-type
|
||||
* disp-ext-type = token
|
||||
* disposition-parm = filename-parm | disp-ext-parm
|
||||
* filename-parm = "filename" "=" value
|
||||
* | "filename*" "=" ext-value
|
||||
* disp-ext-parm = token "=" value
|
||||
* | ext-token "=" ext-value
|
||||
* ext-token = <the characters in token, followed by "*">
|
||||
*/
|
||||
|
||||
var dispositionTypeRegExp = /^([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *(?:$|;)/
|
||||
|
||||
/**
|
||||
* Create an attachment Content-Disposition header.
|
||||
*
|
||||
* @param {string} [filename]
|
||||
* @param {object} [options]
|
||||
* @param {string} [options.type=attachment]
|
||||
* @param {string|boolean} [options.fallback=true]
|
||||
* @return {string}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function contentDisposition(filename, options) {
|
||||
var opts = options || {}
|
||||
|
||||
// get type
|
||||
var type = opts.type || 'attachment'
|
||||
|
||||
// get parameters
|
||||
var params = createparams(filename, opts.fallback)
|
||||
|
||||
// format into string
|
||||
return format(new ContentDisposition(type, params))
|
||||
}
|
||||
|
||||
/**
|
||||
* Create parameters object from filename and fallback.
|
||||
*
|
||||
* @param {string} [filename]
|
||||
* @param {string|boolean} [fallback=true]
|
||||
* @return {object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function createparams(filename, fallback) {
|
||||
if (filename === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
var params = {}
|
||||
|
||||
if (typeof filename !== 'string') {
|
||||
throw new TypeError('filename must be a string')
|
||||
}
|
||||
|
||||
// fallback defaults to true
|
||||
if (fallback === undefined) {
|
||||
fallback = true
|
||||
}
|
||||
|
||||
if (typeof fallback !== 'string' && typeof fallback !== 'boolean') {
|
||||
throw new TypeError('fallback must be a string or boolean')
|
||||
}
|
||||
|
||||
if (typeof fallback === 'string' && nonLatin1RegExp.test(fallback)) {
|
||||
throw new TypeError('fallback must be ISO-8859-1 string')
|
||||
}
|
||||
|
||||
// restrict to file base name
|
||||
var name = basename(filename)
|
||||
|
||||
// determine if name is suitable for quoted string
|
||||
var isQuotedString = textRegExp.test(name)
|
||||
|
||||
// generate fallback name
|
||||
var fallbackName = typeof fallback !== 'string'
|
||||
? fallback && getlatin1(name)
|
||||
: basename(fallback)
|
||||
var hasFallback = typeof fallbackName === 'string' && fallbackName !== name
|
||||
|
||||
// set extended filename parameter
|
||||
if (hasFallback || !isQuotedString || hexEscapeRegExp.test(name)) {
|
||||
params['filename*'] = name
|
||||
}
|
||||
|
||||
// set filename parameter
|
||||
if (isQuotedString || hasFallback) {
|
||||
params.filename = hasFallback
|
||||
? fallbackName
|
||||
: name
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
/**
|
||||
* Format object to Content-Disposition header.
|
||||
*
|
||||
* @param {object} obj
|
||||
* @param {string} obj.type
|
||||
* @param {object} [obj.parameters]
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function format(obj) {
|
||||
var parameters = obj.parameters
|
||||
var type = obj.type
|
||||
|
||||
if (!type || typeof type !== 'string' || !tokenRegExp.test(type)) {
|
||||
throw new TypeError('invalid type')
|
||||
}
|
||||
|
||||
// start with normalized type
|
||||
var string = String(type).toLowerCase()
|
||||
|
||||
// append parameters
|
||||
if (parameters && typeof parameters === 'object') {
|
||||
var param
|
||||
var params = Object.keys(parameters).sort()
|
||||
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
param = params[i]
|
||||
|
||||
var val = param.substr(-1) === '*'
|
||||
? ustring(parameters[param])
|
||||
: qstring(parameters[param])
|
||||
|
||||
string += '; ' + param + '=' + val
|
||||
}
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a RFC 6987 field value (gracefully).
|
||||
*
|
||||
* @param {string} str
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function decodefield(str) {
|
||||
var match = extValueRegExp.exec(str)
|
||||
|
||||
if (!match) {
|
||||
throw new TypeError('invalid extended field value')
|
||||
}
|
||||
|
||||
var charset = match[1].toLowerCase()
|
||||
var encoded = match[2]
|
||||
var value
|
||||
|
||||
// to binary string
|
||||
var binary = encoded.replace(hexEscapeReplaceRegExp, pdecode)
|
||||
|
||||
switch (charset) {
|
||||
case 'iso-8859-1':
|
||||
value = getlatin1(binary)
|
||||
break
|
||||
case 'utf-8':
|
||||
value = new Buffer(binary, 'binary').toString('utf8')
|
||||
break
|
||||
default:
|
||||
throw new TypeError('unsupported charset in extended field')
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ISO-8859-1 version of string.
|
||||
*
|
||||
* @param {string} val
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function getlatin1(val) {
|
||||
// simple Unicode -> ISO-8859-1 transformation
|
||||
return String(val).replace(nonLatin1RegExp, '?')
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Content-Disposition header string.
|
||||
*
|
||||
* @param {string} string
|
||||
* @return {object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse(string) {
|
||||
if (!string || typeof string !== 'string') {
|
||||
throw new TypeError('argument string is required')
|
||||
}
|
||||
|
||||
var match = dispositionTypeRegExp.exec(string)
|
||||
|
||||
if (!match) {
|
||||
throw new TypeError('invalid type format')
|
||||
}
|
||||
|
||||
// normalize type
|
||||
var index = match[0].length
|
||||
var type = match[1].toLowerCase()
|
||||
|
||||
var key
|
||||
var names = []
|
||||
var params = {}
|
||||
var value
|
||||
|
||||
// calculate index to start at
|
||||
index = paramRegExp.lastIndex = match[0].substr(-1) === ';'
|
||||
? index - 1
|
||||
: index
|
||||
|
||||
// match parameters
|
||||
while (match = paramRegExp.exec(string)) {
|
||||
if (match.index !== index) {
|
||||
throw new TypeError('invalid parameter format')
|
||||
}
|
||||
|
||||
index += match[0].length
|
||||
key = match[1].toLowerCase()
|
||||
value = match[2]
|
||||
|
||||
if (names.indexOf(key) !== -1) {
|
||||
throw new TypeError('invalid duplicate parameter')
|
||||
}
|
||||
|
||||
names.push(key)
|
||||
|
||||
if (key.indexOf('*') + 1 === key.length) {
|
||||
// decode extended value
|
||||
key = key.slice(0, -1)
|
||||
value = decodefield(value)
|
||||
|
||||
// overwrite existing value
|
||||
params[key] = value
|
||||
continue
|
||||
}
|
||||
|
||||
if (typeof params[key] === 'string') {
|
||||
continue
|
||||
}
|
||||
|
||||
if (value[0] === '"') {
|
||||
// remove quotes and escapes
|
||||
value = value
|
||||
.substr(1, value.length - 2)
|
||||
.replace(qescRegExp, '$1')
|
||||
}
|
||||
|
||||
params[key] = value
|
||||
}
|
||||
|
||||
if (index !== -1 && index !== string.length) {
|
||||
throw new TypeError('invalid parameter format')
|
||||
}
|
||||
|
||||
return new ContentDisposition(type, params)
|
||||
}
|
||||
|
||||
/**
|
||||
* Percent decode a single character.
|
||||
*
|
||||
* @param {string} str
|
||||
* @param {string} hex
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function pdecode(str, hex) {
|
||||
return String.fromCharCode(parseInt(hex, 16))
|
||||
}
|
||||
|
||||
/**
|
||||
* Percent encode a single character.
|
||||
*
|
||||
* @param {string} char
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function pencode(char) {
|
||||
var hex = String(char)
|
||||
.charCodeAt(0)
|
||||
.toString(16)
|
||||
.toUpperCase()
|
||||
return hex.length === 1
|
||||
? '%0' + hex
|
||||
: '%' + hex
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote a string for HTTP.
|
||||
*
|
||||
* @param {string} val
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function qstring(val) {
|
||||
var str = String(val)
|
||||
|
||||
return '"' + str.replace(quoteRegExp, '\\$1') + '"'
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a Unicode string for HTTP (RFC 5987).
|
||||
*
|
||||
* @param {string} val
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function ustring(val) {
|
||||
var str = String(val)
|
||||
|
||||
// percent encode as UTF-8
|
||||
var encoded = encodeURIComponent(str)
|
||||
.replace(encodeUriAttrCharRegExp, pencode)
|
||||
|
||||
return 'UTF-8\'\'' + encoded
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for parsed Content-Disposition header for v8 optimization
|
||||
*/
|
||||
|
||||
function ContentDisposition(type, parameters) {
|
||||
this.type = type
|
||||
this.parameters = parameters
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
"name": "content-disposition",
|
||||
"description": "Create and parse Content-Disposition header",
|
||||
"version": "0.5.0",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Douglas Christopher Wilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"content-disposition",
|
||||
"http",
|
||||
"rfc6266",
|
||||
"res"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jshttp/content-disposition"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "0.3.2",
|
||||
"mocha": "~1.21.4"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"HISTORY.md",
|
||||
"README.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --reporter spec --bail --check-leaks test/",
|
||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
|
||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
|
||||
},
|
||||
"gitHead": "f3c915f0c9d9f5ec79713dba24c8c6181b73305d",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jshttp/content-disposition/issues"
|
||||
},
|
||||
"homepage": "https://github.com/jshttp/content-disposition",
|
||||
"_id": "content-disposition@0.5.0",
|
||||
"_shasum": "4284fe6ae0630874639e44e80a418c2934135e9e",
|
||||
"_from": "content-disposition@*",
|
||||
"_npmVersion": "1.4.21",
|
||||
"_npmUser": {
|
||||
"name": "dougwilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "dougwilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "4284fe6ae0630874639e44e80a418c2934135e9e",
|
||||
"tarball": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
0.3.0 / 2014-09-07
|
||||
==================
|
||||
|
||||
* Support Node.js 0.6
|
||||
* Throw error when parameter format invalid on parse
|
||||
|
||||
0.2.0 / 2014-06-18
|
||||
==================
|
||||
|
||||
* Add `typer.format()` to format media types
|
||||
|
||||
0.1.0 / 2014-06-17
|
||||
==================
|
||||
|
||||
* Accept `req` as argument to `parse`
|
||||
* Accept `res` as argument to `parse`
|
||||
* Parse media type with extra LWS between type and first parameter
|
||||
|
||||
0.0.0 / 2014-06-13
|
||||
==================
|
||||
|
||||
* Initial implementation
|
|
@ -1,22 +0,0 @@
|
|||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 Douglas Christopher Wilson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,81 +0,0 @@
|
|||
# media-typer
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![Node.js Version][node-version-image]][node-version-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
Simple RFC 6838 media type parser
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ npm install media-typer
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var typer = require('media-typer')
|
||||
```
|
||||
|
||||
### typer.parse(string)
|
||||
|
||||
```js
|
||||
var obj = typer.parse('image/svg+xml; charset=utf-8')
|
||||
```
|
||||
|
||||
Parse a media type string. This will return an object with the following
|
||||
properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):
|
||||
|
||||
- `type`: The type of the media type (always lower case). Example: `'image'`
|
||||
|
||||
- `subtype`: The subtype of the media type (always lower case). Example: `'svg'`
|
||||
|
||||
- `suffix`: The suffix of the media type (always lower case). Example: `'xml'`
|
||||
|
||||
- `parameters`: An object of the parameters in the media type (name of parameter always lower case). Example: `{charset: 'utf-8'}`
|
||||
|
||||
### typer.parse(req)
|
||||
|
||||
```js
|
||||
var obj = typer.parse(req)
|
||||
```
|
||||
|
||||
Parse the `content-type` header from the given `req`. Short-cut for
|
||||
`typer.parse(req.headers['content-type'])`.
|
||||
|
||||
### typer.parse(res)
|
||||
|
||||
```js
|
||||
var obj = typer.parse(res)
|
||||
```
|
||||
|
||||
Parse the `content-type` header set on the given `res`. Short-cut for
|
||||
`typer.parse(res.getHeader('content-type'))`.
|
||||
|
||||
### typer.format(obj)
|
||||
|
||||
```js
|
||||
var obj = typer.format({type: 'image', subtype: 'svg', suffix: 'xml'})
|
||||
```
|
||||
|
||||
Format an object into a media type string. This will return a string of the
|
||||
mime type for the given object. For the properties of the object, see the
|
||||
documentation for `typer.parse(string)`.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/media-typer.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/media-typer
|
||||
[node-version-image]: https://img.shields.io/badge/node.js-%3E%3D_0.6-brightgreen.svg?style=flat
|
||||
[node-version-url]: http://nodejs.org/download/
|
||||
[travis-image]: https://img.shields.io/travis/jshttp/media-typer.svg?style=flat
|
||||
[travis-url]: https://travis-ci.org/jshttp/media-typer
|
||||
[coveralls-image]: https://img.shields.io/coveralls/jshttp/media-typer.svg?style=flat
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/media-typer
|
||||
[downloads-image]: https://img.shields.io/npm/dm/media-typer.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/media-typer
|
|
@ -1,270 +0,0 @@
|
|||
/*!
|
||||
* media-typer
|
||||
* Copyright(c) 2014 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* RegExp to match *( ";" parameter ) in RFC 2616 sec 3.7
|
||||
*
|
||||
* parameter = token "=" ( token | quoted-string )
|
||||
* token = 1*<any CHAR except CTLs or separators>
|
||||
* separators = "(" | ")" | "<" | ">" | "@"
|
||||
* | "," | ";" | ":" | "\" | <">
|
||||
* | "/" | "[" | "]" | "?" | "="
|
||||
* | "{" | "}" | SP | HT
|
||||
* quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
|
||||
* qdtext = <any TEXT except <">>
|
||||
* quoted-pair = "\" CHAR
|
||||
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
* TEXT = <any OCTET except CTLs, but including LWS>
|
||||
* LWS = [CRLF] 1*( SP | HT )
|
||||
* CRLF = CR LF
|
||||
* CR = <US-ASCII CR, carriage return (13)>
|
||||
* LF = <US-ASCII LF, linefeed (10)>
|
||||
* SP = <US-ASCII SP, space (32)>
|
||||
* SHT = <US-ASCII HT, horizontal-tab (9)>
|
||||
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
||||
* OCTET = <any 8-bit sequence of data>
|
||||
*/
|
||||
var paramRegExp = /; *([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *= *("(?:[ !\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u0020-\u007e])*"|[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) */g;
|
||||
var textRegExp = /^[\u0020-\u007e\u0080-\u00ff]+$/
|
||||
var tokenRegExp = /^[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+$/
|
||||
|
||||
/**
|
||||
* RegExp to match quoted-pair in RFC 2616
|
||||
*
|
||||
* quoted-pair = "\" CHAR
|
||||
* CHAR = <any US-ASCII character (octets 0 - 127)>
|
||||
*/
|
||||
var qescRegExp = /\\([\u0000-\u007f])/g;
|
||||
|
||||
/**
|
||||
* RegExp to match chars that must be quoted-pair in RFC 2616
|
||||
*/
|
||||
var quoteRegExp = /([\\"])/g;
|
||||
|
||||
/**
|
||||
* RegExp to match type in RFC 6838
|
||||
*
|
||||
* type-name = restricted-name
|
||||
* subtype-name = restricted-name
|
||||
* restricted-name = restricted-name-first *126restricted-name-chars
|
||||
* restricted-name-first = ALPHA / DIGIT
|
||||
* restricted-name-chars = ALPHA / DIGIT / "!" / "#" /
|
||||
* "$" / "&" / "-" / "^" / "_"
|
||||
* restricted-name-chars =/ "." ; Characters before first dot always
|
||||
* ; specify a facet name
|
||||
* restricted-name-chars =/ "+" ; Characters after last plus always
|
||||
* ; specify a structured syntax suffix
|
||||
* ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
|
||||
* DIGIT = %x30-39 ; 0-9
|
||||
*/
|
||||
var subtypeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.-]{0,126}$/
|
||||
var typeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/
|
||||
var typeRegExp = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
exports.format = format
|
||||
exports.parse = parse
|
||||
|
||||
/**
|
||||
* Format object to media type.
|
||||
*
|
||||
* @param {object} obj
|
||||
* @return {string}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function format(obj) {
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
throw new TypeError('argument obj is required')
|
||||
}
|
||||
|
||||
var parameters = obj.parameters
|
||||
var subtype = obj.subtype
|
||||
var suffix = obj.suffix
|
||||
var type = obj.type
|
||||
|
||||
if (!type || !typeNameRegExp.test(type)) {
|
||||
throw new TypeError('invalid type')
|
||||
}
|
||||
|
||||
if (!subtype || !subtypeNameRegExp.test(subtype)) {
|
||||
throw new TypeError('invalid subtype')
|
||||
}
|
||||
|
||||
// format as type/subtype
|
||||
var string = type + '/' + subtype
|
||||
|
||||
// append +suffix
|
||||
if (suffix) {
|
||||
if (!typeNameRegExp.test(suffix)) {
|
||||
throw new TypeError('invalid suffix')
|
||||
}
|
||||
|
||||
string += '+' + suffix
|
||||
}
|
||||
|
||||
// append parameters
|
||||
if (parameters && typeof parameters === 'object') {
|
||||
var param
|
||||
var params = Object.keys(parameters).sort()
|
||||
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
param = params[i]
|
||||
|
||||
if (!tokenRegExp.test(param)) {
|
||||
throw new TypeError('invalid parameter name')
|
||||
}
|
||||
|
||||
string += '; ' + param + '=' + qstring(parameters[param])
|
||||
}
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse media type to object.
|
||||
*
|
||||
* @param {string|object} string
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function parse(string) {
|
||||
if (!string) {
|
||||
throw new TypeError('argument string is required')
|
||||
}
|
||||
|
||||
// support req/res-like objects as argument
|
||||
if (typeof string === 'object') {
|
||||
string = getcontenttype(string)
|
||||
}
|
||||
|
||||
if (typeof string !== 'string') {
|
||||
throw new TypeError('argument string is required to be a string')
|
||||
}
|
||||
|
||||
var index = string.indexOf(';')
|
||||
var type = index !== -1
|
||||
? string.substr(0, index)
|
||||
: string
|
||||
|
||||
var key
|
||||
var match
|
||||
var obj = splitType(type)
|
||||
var params = {}
|
||||
var value
|
||||
|
||||
paramRegExp.lastIndex = index
|
||||
|
||||
while (match = paramRegExp.exec(string)) {
|
||||
if (match.index !== index) {
|
||||
throw new TypeError('invalid parameter format')
|
||||
}
|
||||
|
||||
index += match[0].length
|
||||
key = match[1].toLowerCase()
|
||||
value = match[2]
|
||||
|
||||
if (value[0] === '"') {
|
||||
// remove quotes and escapes
|
||||
value = value
|
||||
.substr(1, value.length - 2)
|
||||
.replace(qescRegExp, '$1')
|
||||
}
|
||||
|
||||
params[key] = value
|
||||
}
|
||||
|
||||
if (index !== -1 && index !== string.length) {
|
||||
throw new TypeError('invalid parameter format')
|
||||
}
|
||||
|
||||
obj.parameters = params
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content-type from req/res objects.
|
||||
*
|
||||
* @param {object}
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function getcontenttype(obj) {
|
||||
if (typeof obj.getHeader === 'function') {
|
||||
// res-like
|
||||
return obj.getHeader('content-type')
|
||||
}
|
||||
|
||||
if (typeof obj.headers === 'object') {
|
||||
// req-like
|
||||
return obj.headers && obj.headers['content-type']
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote a string if necessary.
|
||||
*
|
||||
* @param {string} val
|
||||
* @return {string}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function qstring(val) {
|
||||
var str = String(val)
|
||||
|
||||
// no need to quote tokens
|
||||
if (tokenRegExp.test(str)) {
|
||||
return str
|
||||
}
|
||||
|
||||
if (str.length > 0 && !textRegExp.test(str)) {
|
||||
throw new TypeError('invalid parameter value')
|
||||
}
|
||||
|
||||
return '"' + str.replace(quoteRegExp, '\\$1') + '"'
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply "type/subtype+siffx" into parts.
|
||||
*
|
||||
* @param {string} string
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function splitType(string) {
|
||||
var match = typeRegExp.exec(string.toLowerCase())
|
||||
|
||||
if (!match) {
|
||||
throw new TypeError('invalid media type')
|
||||
}
|
||||
|
||||
var type = match[1]
|
||||
var subtype = match[2]
|
||||
var suffix
|
||||
|
||||
// suffix after last +
|
||||
var index = subtype.lastIndexOf('+')
|
||||
if (index !== -1) {
|
||||
suffix = subtype.substr(index + 1)
|
||||
subtype = subtype.substr(0, index)
|
||||
}
|
||||
|
||||
var obj = {
|
||||
type: type,
|
||||
subtype: subtype,
|
||||
suffix: suffix
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
{
|
||||
"name": "media-typer",
|
||||
"description": "Simple RFC 6838 media type parser and formatter",
|
||||
"version": "0.3.0",
|
||||
"author": {
|
||||
"name": "Douglas Christopher Wilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jshttp/media-typer"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "0.3.2",
|
||||
"mocha": "~1.21.4",
|
||||
"should": "~4.0.4"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"HISTORY.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --reporter spec --check-leaks --bail test/",
|
||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
|
||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
|
||||
},
|
||||
"gitHead": "d49d41ffd0bb5a0655fa44a59df2ec0bfc835b16",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jshttp/media-typer/issues"
|
||||
},
|
||||
"homepage": "https://github.com/jshttp/media-typer",
|
||||
"_id": "media-typer@0.3.0",
|
||||
"_shasum": "8710d7af0aa626f8fffa1ce00168545263255748",
|
||||
"_from": "media-typer@*",
|
||||
"_npmVersion": "1.4.21",
|
||||
"_npmUser": {
|
||||
"name": "dougwilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "dougwilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "8710d7af0aa626f8fffa1ce00168545263255748",
|
||||
"tarball": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
"buster-format": "0.5.6",
|
||||
"cheerio": "0.17.0",
|
||||
"coffee-script": "1.7.1",
|
||||
"content-disposition": "0.5.0",
|
||||
"decimal": "0.0.2",
|
||||
"docco": "0.6.3",
|
||||
"expect.js": "0.3.1",
|
||||
|
@ -15,7 +14,6 @@
|
|||
"joi": "4.9.0",
|
||||
"jshint": "2.5.5",
|
||||
"marked": "0.3.2",
|
||||
"media-typer": "0.3.0",
|
||||
"moment": "2.6.0",
|
||||
"numeral": "1.5.3",
|
||||
"qs": "2.3.3",
|
||||
|
|
Loading…
Reference in New Issue