restify-clients
Advanced tools
Comparing version 2.4.0 to 2.5.0
@@ -7,2 +7,8 @@ # restify-clients Changelog | ||
## 2.5.0 | ||
* #173: support content-md5 header generated from different node versions. This | ||
adds a new [contentMd5](README.md#contentMd5) StringClient option that can be | ||
used to control content-md5 response header validation. | ||
## 2.4.0 | ||
@@ -9,0 +15,0 @@ |
@@ -21,3 +21,18 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. | ||
assert.optionalObject(options.gzip, 'options.gzip'); | ||
assert.optionalObject(options.contentMd5, 'options.contentMd5'); | ||
if (options.contentMd5) { | ||
assert.optionalArrayOfString(options.contentMd5.encodings, | ||
'options.contentMd5.encodings'); | ||
assert.optionalBool(options.contentMd5.ignore, | ||
'options.contentMd5.ignore'); | ||
if (Array.isArray(options.contentMd5.encodings)) { | ||
options.contentMd5.encodings.forEach(function _checkMd5Enc(enc) { | ||
assert.ok(Buffer.isEncoding(enc), | ||
'encoding "' + enc + '" is an invalid encoding'); | ||
}); | ||
} | ||
} | ||
options.accept = options.accept || 'text/plain'; | ||
@@ -29,3 +44,10 @@ options.name = options.name || 'StringClient'; | ||
HttpClient.call(this, options); | ||
this.contentMd5 = options.contentMd5 || {}; | ||
this.gzip = options.gzip; | ||
if (!this.contentMd5.encodings) { | ||
// The undefined value here is used to make node use the default | ||
// encoding when computing the response content md5 hash. | ||
this.contentMd5.encodings = [undefined]; | ||
} | ||
} | ||
@@ -204,4 +226,5 @@ util.inherits(StringClient, HttpClient); | ||
var gz; | ||
var hash; | ||
var md5; | ||
var md5HashObjects; | ||
var md5Match; | ||
var decoder; | ||
@@ -213,4 +236,10 @@ | ||
if (hash && md5 !== hash.digest('base64')) { | ||
return callback(new Error('BadDigest')); | ||
if (md5HashObjects) { | ||
md5Match = md5HashObjects.some(function (hashObj) { | ||
return hashObj.hash.digest('base64') === md5; | ||
}); | ||
if (!md5Match) { | ||
return callback(new Error('BadDigest'), req, res); | ||
} | ||
} | ||
@@ -229,4 +258,9 @@ | ||
if (md5 && req.method !== 'HEAD' && res.statusCode !== 206) { | ||
hash = crypto.createHash('md5'); | ||
if (md5 && req.method !== 'HEAD' && res.statusCode !== 206 && | ||
!this.contentMd5.ignore) { | ||
md5HashObjects = []; | ||
this.contentMd5.encodings.forEach(function (encoding) { | ||
var hash = crypto.createHash('md5'); | ||
md5HashObjects.push({encoding: encoding, hash: hash}); | ||
}); | ||
} | ||
@@ -251,4 +285,6 @@ | ||
res.on('data', function onData(chunk) { | ||
if (hash) { | ||
hash.update(chunk); | ||
if (md5HashObjects) { | ||
md5HashObjects.forEach(function (hashObj) { | ||
hashObj.hash.update(chunk, hashObj.encoding); | ||
}); | ||
} | ||
@@ -255,0 +291,0 @@ |
{ | ||
"name": "restify-clients", | ||
"version": "2.4.0", | ||
"version": "2.5.0", | ||
"main": "lib/index.js", | ||
@@ -49,14 +49,13 @@ "description": "HttpClient, StringClient, and JsonClient extracted from restify", | ||
"chai": "^4.0.2", | ||
"coveralls": "^2.11.4", | ||
"eslint": "^4.1.1", | ||
"coveralls": "^3.0.2", | ||
"eslint": "^4.19.1", | ||
"istanbul": "^0.4.0", | ||
"jscs": "^2.11.0", | ||
"jscs": "^3.0.7", | ||
"json": "^9.0.4", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^3.4.2", | ||
"mocha": "^5.2.0", | ||
"nock": "^9.0.13", | ||
"nsp": "^2.0.1", | ||
"proxyquire": "^1.8.0", | ||
"proxyquire": "^2.0.1", | ||
"restify": "^4.3.0", | ||
"sinon": "^4.1.2" | ||
"sinon": "^6.1.3" | ||
}, | ||
@@ -69,3 +68,3 @@ "dependencies": { | ||
"keep-alive-agent": "0.0.1", | ||
"lodash": "^4.7.0", | ||
"lodash": "^4.17.10", | ||
"lru-cache": "^4.0.1", | ||
@@ -72,0 +71,0 @@ "mime": "^2.2.0", |
@@ -144,2 +144,3 @@ # restify-clients | ||
|connectTimeout|Number|Amount of time to wait for a socket| | ||
|contentMd5|Object|How response content-md5 headers are handled. See the [contentMd5](#contentMd5) option to StringClient| | ||
|contentType|String|Content-Type header to send| | ||
@@ -235,2 +236,26 @@ |requestTimeout|Number|Amount of time to wait for the request to finish| | ||
#### contentMd5 | ||
The `contentMd5` option to `StringClient` specifies how content-md5 response | ||
headers are handled: | ||
```javascript | ||
var contentMd5 = { | ||
ignore: false, | ||
encodings: undefined | ||
}; | ||
``` | ||
By default if a server responds with a `content-md5` header, `StringClient` will | ||
automatically verify the response body md5 hash, and return a `BadDigest` error | ||
when it does not match. You can disable this behaviour by setting the | ||
`contentMd5.ignore` option to true when creating the StringClient instance. You | ||
can also set the `contentMd5.encodings` property to be an array of encoding | ||
names that StringClient will use to verify the md5. The default encoding is | ||
"utf8" for node 6 and above, and "binary" (a latin1 encoding) for node 4 and | ||
older (as node changed the default crypto hash encoding between versions 4 and | ||
6). To support content-md5 hashes generated by both node 4 and 6 servers, you | ||
can specify `contentMd5.encodings = ["utf8", "binary"]` when creating the | ||
StringClient instance. | ||
#### createStringClient(options) | ||
@@ -237,0 +262,0 @@ |
99723
12
1970
661
Updatedlodash@^4.17.10