socketioMEANseed/server/node_modules/type-is/index.js
server/node_modules/type-is/index.jsRaw
1
2var typer = require('media-typer')
3var mime = require('mime-types')
4
5module.exports = typeofrequest;
6typeofrequest.is = typeis;
7typeofrequest.hasBody = hasbody;
8typeofrequest.normalize = normalize;
9typeofrequest.match = mimeMatch;
10
11/**
12 * Compare a `value` content-type with `types`.
13 * Each `type` can be an extension like `html`,
14 * a special shortcut like `multipart` or `urlencoded`,
15 * or a mime type.
16 *
17 * If no types match, `false` is returned.
18 * Otherwise, the first `type` that matches is returned.
19 *
20 * @param {String} value
21 * @param {Array} types
22 * @return String
23 */
24
25function typeis(value, types_) {
26 var i
27 var types = types_
28
29 // remove parameters and normalize
30 var val = typenormalize(value)
31
32 // no type or invalid
33 if (!val) {
34 return false
35 }
36
37 // support flattened arguments
38 if (types && !Array.isArray(types)) {
39 types = new Array(arguments.length - 1)
40 for (i = 0; i < types.length; i++) {
41 types[i] = arguments[i + 1]
42 }
43 }
44
45 // no types, return the content type
46 if (!types || !types.length) {
47 return val
48 }
49
50 var type
51 for (i = 0; i < types.length; i++) {
52 if (mimeMatch(normalize(type = types[i]), val)) {
53 return type[0] === '+' || ~type.indexOf('*')
54 ? val
55 : type
56 }
57 }
58
59 // no matches
60 return false;
61}
62
63/**
64 * Check if a request has a request body.
65 * A request with a body __must__ either have `transfer-encoding`
66 * or `content-length` headers set.
67 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
68 *
69 * @param {Object} request
70 * @return {Boolean}
71 * @api public
72 */
73
74function hasbody(req) {
75 var headers = req.headers;
76 if ('transfer-encoding' in headers) return true;
77 return !isNaN(headers['content-length']);
78}
79
80/**
81 * Check if the incoming request contains the "Content-Type"
82 * header field, and it contains any of the give mime `type`s.
83 * If there is no request body, `null` is returned.
84 * If there is no content type, `false` is returned.
85 * Otherwise, it returns the first `type` that matches.
86 *
87 * Examples:
88 *
89 * // With Content-Type: text/html; charset=utf-8
90 * this.is('html'); // => 'html'
91 * this.is('text/html'); // => 'text/html'
92 * this.is('text/*', 'application/json'); // => 'text/html'
93 *
94 * // When Content-Type is application/json
95 * this.is('json', 'urlencoded'); // => 'json'
96 * this.is('application/json'); // => 'application/json'
97 * this.is('html', 'application/*'); // => 'application/json'
98 *
99 * this.is('html'); // => false
100 *
101 * @param {String|Array} types...
102 * @return {String|false|null}
103 * @api public
104 */
105
106function typeofrequest(req, types_) {
107 var types = types_
108
109 // no body
110 if (!hasbody(req)) {
111 return null
112 }
113
114 // support flattened arguments
115 if (arguments.length > 2) {
116 types = new Array(arguments.length - 1)
117 for (var i = 0; i < types.length; i++) {
118 types[i] = arguments[i + 1]
119 }
120 }
121
122 // request content type
123 var value = req.headers['content-type']
124
125 return typeis(value, types);
126}
127
128/**
129 * Normalize a mime type.
130 * If it's a shorthand, expand it to a valid mime type.
131 *
132 * In general, you probably want:
133 *
134 * var type = is(req, ['urlencoded', 'json', 'multipart']);
135 *
136 * Then use the appropriate body parsers.
137 * These three are the most common request body types
138 * and are thus ensured to work.
139 *
140 * @param {String} type
141 * @api private
142 */
143
144function normalize(type) {
145 switch (type) {
146 case 'urlencoded': return 'application/x-www-form-urlencoded';
147 case 'multipart':
148 type = 'multipart/*';
149 break;
150 }
151
152 return type[0] === '+' || ~type.indexOf('/')
153 ? type
154 : mime.lookup(type)
155}
156
157/**
158 * Check if `exected` mime type
159 * matches `actual` mime type with
160 * wildcard and +suffix support.
161 *
162 * @param {String} expected
163 * @param {String} actual
164 * @return {Boolean}
165 * @api private
166 */
167
168function mimeMatch(expected, actual) {
169 // invalid type
170 if (expected === false) {
171 return false
172 }
173
174 // exact match
175 if (expected === actual) {
176 return true
177 }
178
179 actual = actual.split('/');
180
181 if (expected[0] === '+') {
182 // support +suffix
183 return Boolean(actual[1])
184 && expected.length <= actual[1].length
185 && expected === actual[1].substr(0 - expected.length)
186 }
187
188 if (!~expected.indexOf('*')) return false;
189
190 expected = expected.split('/');
191
192 if (expected[0] === '*') {
193 // support */yyy
194 return expected[1] === actual[1]
195 }
196
197 if (expected[1] === '*') {
198 // support xxx/*
199 return expected[0] === actual[0]
200 }
201
202 if (expected[1][0] === '*' && expected[1][1] === '+') {
203 // support xxx/*+zzz
204 return expected[0] === actual[0]
205 && expected[1].length <= actual[1].length + 1
206 && expected[1].substr(1) === actual[1].substr(1 - expected[1].length)
207 }
208
209 return false
210}
211
212/**
213 * Normalize a type and remove parameters.
214 *
215 * @param {string} value
216 * @return {string}
217 * @api private
218 */
219
220function typenormalize(value) {
221 try {
222 var type = typer.parse(value)
223 delete type.parameters
224 return typer.format(type)
225 } catch (err) {
226 return null
227 }
228}