arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
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}