content-type 1.0.0 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/HISTORY.md CHANGED
@@ -1,3 +1,23 @@
1
+ 1.0.4 / 2017-09-11
2
+ ==================
3
+
4
+ * perf: skip parameter parsing when no parameters
5
+
6
+ 1.0.3 / 2017-09-10
7
+ ==================
8
+
9
+ * perf: remove argument reassignment
10
+
11
+ 1.0.2 / 2016-05-09
12
+ ==================
13
+
14
+ * perf: enable strict mode
15
+
16
+ 1.0.1 / 2015-02-13
17
+ ==================
18
+
19
+ * Improve missing `Content-Type` header error message
20
+
1
21
  1.0.0 / 2015-02-01
2
22
  ==================
3
23
 
package/README.md CHANGED
@@ -35,6 +35,8 @@ properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):
35
35
  - `parameters`: An object of the parameters in the media type (name of parameter
36
36
  always lower case). Example: `{charset: 'utf-8'}`
37
37
 
38
+ Throws a `TypeError` if the string is missing or invalid.
39
+
38
40
  ### contentType.parse(req)
39
41
 
40
42
  ```js
@@ -44,6 +46,8 @@ var obj = contentType.parse(req)
44
46
  Parse the `content-type` header from the given `req`. Short-cut for
45
47
  `contentType.parse(req.headers['content-type'])`.
46
48
 
49
+ Throws a `TypeError` if the `Content-Type` header is missing or invalid.
50
+
47
51
  ### contentType.parse(res)
48
52
 
49
53
  ```js
@@ -53,6 +57,8 @@ var obj = contentType.parse(res)
53
57
  Parse the `content-type` header set on the given `res`. Short-cut for
54
58
  `contentType.parse(res.getHeader('content-type'))`.
55
59
 
60
+ Throws a `TypeError` if the `Content-Type` header is missing or invalid.
61
+
56
62
  ### contentType.format(obj)
57
63
 
58
64
  ```js
@@ -68,6 +74,8 @@ shown that produce the string `'image/svg+xml; charset=utf-8'`):
68
74
  - `parameters`: An object of the parameters in the media type (name of the
69
75
  parameter will be lower-cased). Example: `{charset: 'utf-8'}`
70
76
 
77
+ Throws a `TypeError` if the object contains an invalid type or parameter names.
78
+
71
79
  ## License
72
80
 
73
81
  [MIT](LICENSE)
package/index.js CHANGED
@@ -4,6 +4,8 @@
4
4
  * MIT Licensed
5
5
  */
6
6
 
7
+ 'use strict'
8
+
7
9
  /**
8
10
  * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1
9
11
  *
@@ -18,9 +20,9 @@
18
20
  * obs-text = %x80-FF
19
21
  * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
20
22
  */
21
- var paramRegExp = /; *([!#$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+) */g
22
- var textRegExp = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/
23
- var tokenRegExp = /^[!#$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+$/
23
+ var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g
24
+ var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/
25
+ var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/
24
26
 
25
27
  /**
26
28
  * RegExp to match quoted-pair in RFC 7230 sec 3.2.6
@@ -28,21 +30,21 @@ var tokenRegExp = /^[!#$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+$/
28
30
  * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
29
31
  * obs-text = %x80-FF
30
32
  */
31
- var qescRegExp = /\\([\u000b\u0020-\u00ff])/g
33
+ var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g
32
34
 
33
35
  /**
34
36
  * RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6
35
37
  */
36
- var quoteRegExp = /([\\"])/g
38
+ var QUOTE_REGEXP = /([\\"])/g
37
39
 
38
40
  /**
39
- * RegExp to match type in RFC 6838
41
+ * RegExp to match type in RFC 7231 sec 3.1.1.1
40
42
  *
41
43
  * media-type = type "/" subtype
42
44
  * type = token
43
45
  * subtype = token
44
46
  */
45
- var typeRegExp = /^[!#$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+\/[!#$%&'\*\+\-\.\^_`\|~0-9A-Za-z]+$/
47
+ var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/
46
48
 
47
49
  /**
48
50
  * Module exports.
@@ -60,7 +62,7 @@ exports.parse = parse
60
62
  * @public
61
63
  */
62
64
 
63
- function format(obj) {
65
+ function format (obj) {
64
66
  if (!obj || typeof obj !== 'object') {
65
67
  throw new TypeError('argument obj is required')
66
68
  }
@@ -68,7 +70,7 @@ function format(obj) {
68
70
  var parameters = obj.parameters
69
71
  var type = obj.type
70
72
 
71
- if (!type || !typeRegExp.test(type)) {
73
+ if (!type || !TYPE_REGEXP.test(type)) {
72
74
  throw new TypeError('invalid type')
73
75
  }
74
76
 
@@ -82,7 +84,7 @@ function format(obj) {
82
84
  for (var i = 0; i < params.length; i++) {
83
85
  param = params[i]
84
86
 
85
- if (!tokenRegExp.test(param)) {
87
+ if (!TOKEN_REGEXP.test(param)) {
86
88
  throw new TypeError('invalid parameter name')
87
89
  }
88
90
 
@@ -101,57 +103,61 @@ function format(obj) {
101
103
  * @public
102
104
  */
103
105
 
104
- function parse(string) {
106
+ function parse (string) {
105
107
  if (!string) {
106
108
  throw new TypeError('argument string is required')
107
109
  }
108
110
 
109
111
  // support req/res-like objects as argument
110
- if (typeof string === 'object') {
111
- string = getcontenttype(string)
112
- }
112
+ var header = typeof string === 'object'
113
+ ? getcontenttype(string)
114
+ : string
113
115
 
114
- if (typeof string !== 'string') {
116
+ if (typeof header !== 'string') {
115
117
  throw new TypeError('argument string is required to be a string')
116
118
  }
117
119
 
118
- var index = string.indexOf(';')
120
+ var index = header.indexOf(';')
119
121
  var type = index !== -1
120
- ? string.substr(0, index).trim()
121
- : string.trim()
122
+ ? header.substr(0, index).trim()
123
+ : header.trim()
122
124
 
123
- if (!typeRegExp.test(type)) {
125
+ if (!TYPE_REGEXP.test(type)) {
124
126
  throw new TypeError('invalid media type')
125
127
  }
126
128
 
127
- var key
128
- var match
129
129
  var obj = new ContentType(type.toLowerCase())
130
- var value
131
130
 
132
- paramRegExp.lastIndex = index
131
+ // parse parameters
132
+ if (index !== -1) {
133
+ var key
134
+ var match
135
+ var value
133
136
 
134
- while (match = paramRegExp.exec(string)) {
135
- if (match.index !== index) {
136
- throw new TypeError('invalid parameter format')
137
- }
137
+ PARAM_REGEXP.lastIndex = index
138
138
 
139
- index += match[0].length
140
- key = match[1].toLowerCase()
141
- value = match[2]
139
+ while ((match = PARAM_REGEXP.exec(header))) {
140
+ if (match.index !== index) {
141
+ throw new TypeError('invalid parameter format')
142
+ }
142
143
 
143
- if (value[0] === '"') {
144
- // remove quotes and escapes
145
- value = value
146
- .substr(1, value.length - 2)
147
- .replace(qescRegExp, '$1')
148
- }
144
+ index += match[0].length
145
+ key = match[1].toLowerCase()
146
+ value = match[2]
149
147
 
150
- obj.parameters[key] = value
151
- }
148
+ if (value[0] === '"') {
149
+ // remove quotes and escapes
150
+ value = value
151
+ .substr(1, value.length - 2)
152
+ .replace(QESC_REGEXP, '$1')
153
+ }
152
154
 
153
- if (index !== -1 && index !== string.length) {
154
- throw new TypeError('invalid parameter format')
155
+ obj.parameters[key] = value
156
+ }
157
+
158
+ if (index !== header.length) {
159
+ throw new TypeError('invalid parameter format')
160
+ }
155
161
  }
156
162
 
157
163
  return obj
@@ -165,16 +171,22 @@ function parse(string) {
165
171
  * @private
166
172
  */
167
173
 
168
- function getcontenttype(obj) {
174
+ function getcontenttype (obj) {
175
+ var header
176
+
169
177
  if (typeof obj.getHeader === 'function') {
170
178
  // res-like
171
- return obj.getHeader('content-type')
179
+ header = obj.getHeader('content-type')
180
+ } else if (typeof obj.headers === 'object') {
181
+ // req-like
182
+ header = obj.headers && obj.headers['content-type']
172
183
  }
173
184
 
174
- if (typeof obj.headers === 'object') {
175
- // req-like
176
- return obj.headers && obj.headers['content-type']
185
+ if (typeof header !== 'string') {
186
+ throw new TypeError('content-type header is missing from object')
177
187
  }
188
+
189
+ return header
178
190
  }
179
191
 
180
192
  /**
@@ -185,26 +197,26 @@ function getcontenttype(obj) {
185
197
  * @private
186
198
  */
187
199
 
188
- function qstring(val) {
200
+ function qstring (val) {
189
201
  var str = String(val)
190
202
 
191
203
  // no need to quote tokens
192
- if (tokenRegExp.test(str)) {
204
+ if (TOKEN_REGEXP.test(str)) {
193
205
  return str
194
206
  }
195
207
 
196
- if (str.length > 0 && !textRegExp.test(str)) {
208
+ if (str.length > 0 && !TEXT_REGEXP.test(str)) {
197
209
  throw new TypeError('invalid parameter value')
198
210
  }
199
211
 
200
- return '"' + str.replace(quoteRegExp, '\\$1') + '"'
212
+ return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"'
201
213
  }
202
214
 
203
215
  /**
204
216
  * Class to represent a content type.
205
217
  * @private
206
218
  */
207
- function ContentType(type) {
219
+ function ContentType (type) {
208
220
  this.parameters = Object.create(null)
209
221
  this.type = type
210
222
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "content-type",
3
3
  "description": "Create and parse HTTP Content-Type header",
4
- "version": "1.0.0",
4
+ "version": "1.0.4",
5
5
  "author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -13,7 +13,13 @@
13
13
  ],
14
14
  "repository": "jshttp/content-type",
15
15
  "devDependencies": {
16
- "istanbul": "0.3.5",
16
+ "eslint": "3.19.0",
17
+ "eslint-config-standard": "10.2.1",
18
+ "eslint-plugin-import": "2.7.0",
19
+ "eslint-plugin-node": "5.1.1",
20
+ "eslint-plugin-promise": "3.5.0",
21
+ "eslint-plugin-standard": "3.0.1",
22
+ "istanbul": "0.4.5",
17
23
  "mocha": "~1.21.5"
18
24
  },
19
25
  "files": [
@@ -26,6 +32,7 @@
26
32
  "node": ">= 0.6"
27
33
  },
28
34
  "scripts": {
35
+ "lint": "eslint .",
29
36
  "test": "mocha --reporter spec --check-leaks --bail test/",
30
37
  "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
31
38
  "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/"