3 * Copyright(c) 2009-2013 TJ Holowaychuk
4 * Copyright(c) 2014-2015 Douglas Christopher Wilson
11 * Module dependencies.
15 var Buffer
= require('safe-buffer').Buffer
16 var contentType
= require('content-type');
17 var etag
= require('etag');
18 var mime
= require('mime-types')
19 var proxyaddr
= require('proxy-addr');
20 var qs
= require('qs');
21 var querystring
= require('querystring');
24 * Return strong ETag for `body`.
26 * @param {String|Buffer} body
27 * @param {String} [encoding]
32 exports
.etag
= createETagGenerator({ weak
: false })
35 * Return weak ETag for `body`.
37 * @param {String|Buffer} body
38 * @param {String} [encoding]
43 exports
.wetag
= createETagGenerator({ weak
: true })
46 * Normalize the given `type`, for example "html" becomes "text/html".
48 * @param {String} type
53 exports
.normalizeType = function(type
){
54 return ~type
.indexOf('/')
56 : { value
: (mime
.lookup(type
) || 'application/octet-stream'), params
: {} }
60 * Normalize `types`, for example "html" becomes "text/html".
62 * @param {Array} types
67 exports
.normalizeTypes = function(types
){
70 for (var i
= 0; i
< types
.length
; ++i
) {
71 ret
.push(exports
.normalizeType(types
[i
]));
78 * Parse accept params `str` returning an
79 * object with `.value`, `.quality` and `.params`.
86 function acceptParams (str
) {
87 var parts
= str
.split(/ *; */
);
88 var ret
= { value
: parts
[0], quality
: 1, params
: {} }
90 for (var i
= 1; i
< parts
.length
; ++i
) {
91 var pms
= parts
[i
].split(/ *= */
);
93 ret
.quality
= parseFloat(pms
[1]);
95 ret
.params
[pms
[0]] = pms
[1];
103 * Compile "etag" value to function.
105 * @param {Boolean|String|Function} val
110 exports
.compileETag = function(val
) {
113 if (typeof val
=== 'function') {
128 throw new TypeError('unknown value for etag function: ' + val
);
135 * Compile "query parser" value to function.
137 * @param {String|Function} val
142 exports
.compileQueryParser
= function compileQueryParser(val
) {
145 if (typeof val
=== 'function') {
152 fn
= querystring
.parse
;
157 fn
= parseExtendedQueryString
;
160 throw new TypeError('unknown value for query parser function: ' + val
);
167 * Compile "proxy trust" value to function.
169 * @param {Boolean|String|Number|Array|Function} val
174 exports
.compileTrust = function(val
) {
175 if (typeof val
=== 'function') return val
;
178 // Support plain true/false
179 return function(){ return true };
182 if (typeof val
=== 'number') {
183 // Support trusting hop count
184 return function(a
, i
){ return i
< val
};
187 if (typeof val
=== 'string') {
188 // Support comma-separated values
190 .map(function (v
) { return v
.trim() })
193 return proxyaddr
.compile(val
|| []);
197 * Set the charset in a given Content-Type string.
199 * @param {String} type
200 * @param {String} charset
205 exports
.setCharset
= function setCharset(type
, charset
) {
206 if (!type
|| !charset
) {
211 var parsed
= contentType
.parse(type
);
214 parsed
.parameters
.charset
= charset
;
217 return contentType
.format(parsed
);
221 * Create an ETag generator function, generating ETags with
224 * @param {object} options
229 function createETagGenerator (options
) {
230 return function generateETag (body
, encoding
) {
231 var buf
= !Buffer
.isBuffer(body
)
232 ? Buffer
.from(body
, encoding
)
235 return etag(buf
, options
)
240 * Parse an extended query string with qs.
242 * @param {String} str
247 function parseExtendedQueryString(str
) {
248 return qs
.parse(str
, {
249 allowPrototypes
: true