Initial commit for OpenECOMP SDN-C OA&M
[sdnc/oam.git] / dgbuilder / dgeflows / node_modules / body-parser / node_modules / type-is / index.js
1
2 var typer = require('media-typer')
3 var mime = require('mime-types')
4
5 module.exports = typeofrequest;
6 typeofrequest.is = typeis;
7 typeofrequest.hasBody = hasbody;
8 typeofrequest.normalize = normalize;
9 typeofrequest.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
25 function 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
74 function 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
106 function 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
144 function 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
168 function 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
220 function 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 }