source: trip-planner-front/node_modules/media-typer/index.js@ 6c1585f

Last change on this file since 6c1585f was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*!
2 * media-typer
3 * Copyright(c) 2014 Douglas Christopher Wilson
4 * MIT Licensed
5 */
6
7/**
8 * RegExp to match *( ";" parameter ) in RFC 2616 sec 3.7
9 *
10 * parameter = token "=" ( token | quoted-string )
11 * token = 1*<any CHAR except CTLs or separators>
12 * separators = "(" | ")" | "<" | ">" | "@"
13 * | "," | ";" | ":" | "\" | <">
14 * | "/" | "[" | "]" | "?" | "="
15 * | "{" | "}" | SP | HT
16 * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
17 * qdtext = <any TEXT except <">>
18 * quoted-pair = "\" CHAR
19 * CHAR = <any US-ASCII character (octets 0 - 127)>
20 * TEXT = <any OCTET except CTLs, but including LWS>
21 * LWS = [CRLF] 1*( SP | HT )
22 * CRLF = CR LF
23 * CR = <US-ASCII CR, carriage return (13)>
24 * LF = <US-ASCII LF, linefeed (10)>
25 * SP = <US-ASCII SP, space (32)>
26 * SHT = <US-ASCII HT, horizontal-tab (9)>
27 * CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
28 * OCTET = <any 8-bit sequence of data>
29 */
30var paramRegExp = /; *([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *= *("(?:[ !\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u0020-\u007e])*"|[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) */g;
31var textRegExp = /^[\u0020-\u007e\u0080-\u00ff]+$/
32var tokenRegExp = /^[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+$/
33
34/**
35 * RegExp to match quoted-pair in RFC 2616
36 *
37 * quoted-pair = "\" CHAR
38 * CHAR = <any US-ASCII character (octets 0 - 127)>
39 */
40var qescRegExp = /\\([\u0000-\u007f])/g;
41
42/**
43 * RegExp to match chars that must be quoted-pair in RFC 2616
44 */
45var quoteRegExp = /([\\"])/g;
46
47/**
48 * RegExp to match type in RFC 6838
49 *
50 * type-name = restricted-name
51 * subtype-name = restricted-name
52 * restricted-name = restricted-name-first *126restricted-name-chars
53 * restricted-name-first = ALPHA / DIGIT
54 * restricted-name-chars = ALPHA / DIGIT / "!" / "#" /
55 * "$" / "&" / "-" / "^" / "_"
56 * restricted-name-chars =/ "." ; Characters before first dot always
57 * ; specify a facet name
58 * restricted-name-chars =/ "+" ; Characters after last plus always
59 * ; specify a structured syntax suffix
60 * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
61 * DIGIT = %x30-39 ; 0-9
62 */
63var subtypeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.-]{0,126}$/
64var typeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/
65var typeRegExp = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
66
67/**
68 * Module exports.
69 */
70
71exports.format = format
72exports.parse = parse
73
74/**
75 * Format object to media type.
76 *
77 * @param {object} obj
78 * @return {string}
79 * @api public
80 */
81
82function format(obj) {
83 if (!obj || typeof obj !== 'object') {
84 throw new TypeError('argument obj is required')
85 }
86
87 var parameters = obj.parameters
88 var subtype = obj.subtype
89 var suffix = obj.suffix
90 var type = obj.type
91
92 if (!type || !typeNameRegExp.test(type)) {
93 throw new TypeError('invalid type')
94 }
95
96 if (!subtype || !subtypeNameRegExp.test(subtype)) {
97 throw new TypeError('invalid subtype')
98 }
99
100 // format as type/subtype
101 var string = type + '/' + subtype
102
103 // append +suffix
104 if (suffix) {
105 if (!typeNameRegExp.test(suffix)) {
106 throw new TypeError('invalid suffix')
107 }
108
109 string += '+' + suffix
110 }
111
112 // append parameters
113 if (parameters && typeof parameters === 'object') {
114 var param
115 var params = Object.keys(parameters).sort()
116
117 for (var i = 0; i < params.length; i++) {
118 param = params[i]
119
120 if (!tokenRegExp.test(param)) {
121 throw new TypeError('invalid parameter name')
122 }
123
124 string += '; ' + param + '=' + qstring(parameters[param])
125 }
126 }
127
128 return string
129}
130
131/**
132 * Parse media type to object.
133 *
134 * @param {string|object} string
135 * @return {Object}
136 * @api public
137 */
138
139function parse(string) {
140 if (!string) {
141 throw new TypeError('argument string is required')
142 }
143
144 // support req/res-like objects as argument
145 if (typeof string === 'object') {
146 string = getcontenttype(string)
147 }
148
149 if (typeof string !== 'string') {
150 throw new TypeError('argument string is required to be a string')
151 }
152
153 var index = string.indexOf(';')
154 var type = index !== -1
155 ? string.substr(0, index)
156 : string
157
158 var key
159 var match
160 var obj = splitType(type)
161 var params = {}
162 var value
163
164 paramRegExp.lastIndex = index
165
166 while (match = paramRegExp.exec(string)) {
167 if (match.index !== index) {
168 throw new TypeError('invalid parameter format')
169 }
170
171 index += match[0].length
172 key = match[1].toLowerCase()
173 value = match[2]
174
175 if (value[0] === '"') {
176 // remove quotes and escapes
177 value = value
178 .substr(1, value.length - 2)
179 .replace(qescRegExp, '$1')
180 }
181
182 params[key] = value
183 }
184
185 if (index !== -1 && index !== string.length) {
186 throw new TypeError('invalid parameter format')
187 }
188
189 obj.parameters = params
190
191 return obj
192}
193
194/**
195 * Get content-type from req/res objects.
196 *
197 * @param {object}
198 * @return {Object}
199 * @api private
200 */
201
202function getcontenttype(obj) {
203 if (typeof obj.getHeader === 'function') {
204 // res-like
205 return obj.getHeader('content-type')
206 }
207
208 if (typeof obj.headers === 'object') {
209 // req-like
210 return obj.headers && obj.headers['content-type']
211 }
212}
213
214/**
215 * Quote a string if necessary.
216 *
217 * @param {string} val
218 * @return {string}
219 * @api private
220 */
221
222function qstring(val) {
223 var str = String(val)
224
225 // no need to quote tokens
226 if (tokenRegExp.test(str)) {
227 return str
228 }
229
230 if (str.length > 0 && !textRegExp.test(str)) {
231 throw new TypeError('invalid parameter value')
232 }
233
234 return '"' + str.replace(quoteRegExp, '\\$1') + '"'
235}
236
237/**
238 * Simply "type/subtype+siffx" into parts.
239 *
240 * @param {string} string
241 * @return {Object}
242 * @api private
243 */
244
245function splitType(string) {
246 var match = typeRegExp.exec(string.toLowerCase())
247
248 if (!match) {
249 throw new TypeError('invalid media type')
250 }
251
252 var type = match[1]
253 var subtype = match[2]
254 var suffix
255
256 // suffix after last +
257 var index = subtype.lastIndexOf('+')
258 if (index !== -1) {
259 suffix = subtype.substr(index + 1)
260 subtype = subtype.substr(0, index)
261 }
262
263 var obj = {
264 type: type,
265 subtype: subtype,
266 suffix: suffix
267 }
268
269 return obj
270}
Note: See TracBrowser for help on using the repository browser.