Comparing version 0.3.2-beta2 to 0.4.0-beta1
@@ -152,5 +152,9 @@ 'use strict'; | ||
* {statusCode, headers, getHeader(), body: {}} | ||
* | ||
* @param {number} maxSize (defaults to 256KiB) | ||
*/ | ||
withBufferJsonResponseHandler() { | ||
return this.withConfig({responseHandler: responseHandlerHelpers.bufferJsonResponseHandler}); | ||
withBufferJsonResponseHandler(maxSize) { | ||
return this.withConfig({ | ||
responseHandler: (response) => responseHandlerHelpers.bufferJsonResponseHandler(response, maxSize) | ||
}); | ||
} | ||
@@ -163,5 +167,9 @@ | ||
* {statusCode, headers, getHeader(), body: Buffer} | ||
* | ||
* @param {number} maxSize (defaults to 256KiB) | ||
*/ | ||
withBufferBodyResponseHandler() { | ||
return this.withConfig({responseHandler: responseHandlerHelpers.bufferBodyResponseHandler}); | ||
withBufferBodyResponseHandler(maxSize) { | ||
return this.withConfig({ | ||
responseHandler: (response) => responseHandlerHelpers.bufferBodyResponseHandler(response, maxSize) | ||
}); | ||
} | ||
@@ -185,2 +193,9 @@ | ||
* {statusCode, headers, getHeader(), body: JSON} | ||
* | ||
* Your responseHandler will be called with a WrappedResponse object and | ||
* must return a promise. The resolved value of the promise will be the | ||
* value which is returned as the resolved value of builder.send(). | ||
* | ||
* Your responseHandler must consume the response in some way, at minimum | ||
* you can WrappedResponse.discard() it. | ||
*/ | ||
@@ -209,15 +224,2 @@ withResponseHandler(responseHandler) { | ||
/** | ||
* Set the maximum response buffer size in bytes. | ||
* | ||
* Defaults to 256KiB. | ||
* | ||
* By default the response is buffered until completion and then JSON parsed. | ||
* If the server response exceeds this size the socket will be closed and | ||
* the promise will be rejected. | ||
*/ | ||
withResponseBufferSize(responseBufferSize) { | ||
return this.withConfig({responseBufferSize}); | ||
} | ||
/** | ||
* Set a custom filter which has access to the request/responses. | ||
@@ -224,0 +226,0 @@ * |
'use strict'; | ||
const sendRequestHelpers = require('./sendRequest'); | ||
const responseValidatorHelpers = require('./responseValidator'); | ||
const responseHandlerHelpers = require('./responseHandler'); | ||
@@ -13,7 +12,6 @@ | ||
sendRequestFn: sendRequestHelpers.sendEmptyBody, | ||
responseValidator: responseValidatorHelpers.expect200Response, | ||
responseHandler: responseHandlerHelpers.defaultResponseHandler, | ||
responseValidator: null, | ||
responseHandler: null, | ||
errorResponseHandler: responseHandlerHelpers.defaultErrorResponseHandler, | ||
timeout: 60000, | ||
responseBufferSize: 256 * 1024 | ||
timeout: null | ||
}; |
@@ -96,26 +96,15 @@ 'use strict'; | ||
function waitForResponseHandler(requestConfig, httpResponse) { | ||
return new p.Promise((resolve, reject) => { | ||
const wrappedResponse = new WrappedResponse(httpResponse, requestConfig.responseBufferSize); | ||
try { | ||
const wrappedResponse = new WrappedResponse(httpResponse); | ||
if (requestConfig.responseValidator(wrappedResponse)) { | ||
requestConfig.responseHandler(wrappedResponse) | ||
.then(resolve, reject); | ||
return requestConfig.responseHandler(wrappedResponse); | ||
} else { | ||
requestConfig.errorResponseHandler(wrappedResponse) | ||
.then((response) => throwResponseError(requestConfig, response)) | ||
.catch(reject); | ||
return requestConfig.errorResponseHandler(wrappedResponse) | ||
.then((response) => throwResponseError(requestConfig, response)); | ||
} | ||
}); | ||
} catch (err) { | ||
return p.Promise.reject(err); | ||
} | ||
} | ||
function supportLongStackTracesWithQ(err) { | ||
// Q needs some help to make the stack trace longer because the callback in | ||
// makeRequest below, httpRequest.on('response'), is not linked to the original | ||
// promise chain. | ||
// See https://github.com/kriskowal/q/blob/ee2b09274e2b03a6fe729efc53b44a71ee75b735/q.js#L381 | ||
err.stack = err.stack.replace('From previous event:', 'From older previous event:'); | ||
throw err; | ||
} | ||
function makeRequest(requestConfig) { | ||
@@ -134,5 +123,5 @@ return new p.Promise((resolve, reject) => { | ||
requestConfig.sendRequestFn(httpRequest); | ||
}).catch(supportLongStackTracesWithQ); | ||
}); | ||
} | ||
module.exports = makeRequest; |
'use strict'; | ||
function formatStandardResponse(wrappedResponse, body) { | ||
return { | ||
statusCode: wrappedResponse.statusCode, | ||
headers: wrappedResponse.headers, | ||
getHeader: wrappedResponse.getHeader.bind(wrappedResponse), | ||
body | ||
}; | ||
} | ||
function isJson(contentType) { | ||
@@ -30,4 +21,16 @@ if (!contentType) { | ||
function defaultResponseHandler(wrappedResponse) { | ||
// Be strict with normal responses, if they don't look like JSON then fail explicitly | ||
function defaultErrorResponseHandler(wrappedResponse) { | ||
// We're in error handling mode, lets try hard to give something useful. | ||
// If we cannot parse as JSON then we'll try to just store the response in a Buffer. | ||
// It may provide useful info if dumped to a log file. | ||
let promise; | ||
if (isJson(wrappedResponse.getHeader('Content-Type'))) { | ||
promise = wrappedResponse.bufferJson(); | ||
} else { | ||
promise = wrappedResponse.bufferBody(); | ||
} | ||
return promise.then((body) => wrappedResponse.getStandardResponse(body)); | ||
} | ||
function bufferJsonResponseHandler(wrappedResponse, maxSize) { | ||
const contentType = wrappedResponse.getHeader('Content-Type'); | ||
@@ -41,33 +44,36 @@ if (!isJson(contentType)) { | ||
return bufferJsonResponseHandler(wrappedResponse); | ||
return wrappedResponse.bufferJson(maxSize) | ||
.then((body) => wrappedResponse.getStandardResponse(body)); | ||
} | ||
function defaultErrorResponseHandler(wrappedResponse) { | ||
// We're in error handling mode, lets try hard to give something useful. | ||
// If we cannot parse as JSON then we'll try to just store the response in a Buffer. | ||
// It may provide useful info if dumped to a log file. | ||
if (isJson(wrappedResponse.getHeader('Content-Type'))) { | ||
return bufferJsonResponseHandler(wrappedResponse); | ||
} else { | ||
return bufferBodyResponseHandler(wrappedResponse); | ||
} | ||
function bufferBodyResponseHandler(wrappedResponse, maxSize) { | ||
return wrappedResponse.bufferBody(maxSize) | ||
.then((body) => { | ||
const response = wrappedResponse.getStandardResponse(body); | ||
Object.defineProperty(response, 'toJSON', {value: prettyPrintBufferBodyResponse}); | ||
return response; | ||
}); | ||
} | ||
function bufferJsonResponseHandler(wrappedResponse) { | ||
return wrappedResponse.bufferJson() | ||
.then((body) => formatStandardResponse(wrappedResponse, body)); | ||
function prettyPrintBufferBodyResponse() { | ||
const self = this; // eslint-disable-line no-invalid-this | ||
const result = Object.assign({}, self); | ||
result.body = Array.from(self.body) | ||
.map((ch) => { | ||
if (ch > 31 && ch < 127) { | ||
return String.fromCharCode(ch); | ||
} else { | ||
return '?'; | ||
} | ||
}) | ||
.join(''); | ||
return result; | ||
} | ||
function bufferBodyResponseHandler(wrappedResponse) { | ||
return wrappedResponse.bufferBody() | ||
.then((body) => formatStandardResponse(wrappedResponse, body)); | ||
} | ||
function discardBodyResponseHandler(wrappedResponse) { | ||
return wrappedResponse.discard() | ||
.then(() => formatStandardResponse(wrappedResponse, null)); | ||
.then(() => wrappedResponse.getStandardResponse(null)); | ||
} | ||
module.exports = { | ||
defaultResponseHandler, | ||
defaultErrorResponseHandler, | ||
@@ -74,0 +80,0 @@ bufferJsonResponseHandler, |
'use strict'; | ||
function expect200Response(wrappedResponse) { | ||
return wrappedResponse.statusCode === 200; | ||
} | ||
function createExpectStatusValidator(expectStatus) { | ||
@@ -14,4 +10,3 @@ return function expectStatusValidator(wrappedResponse) { | ||
module.exports = { | ||
expect200Response, | ||
createExpectStatusValidator | ||
}; |
@@ -6,8 +6,8 @@ 'use strict'; | ||
const DEFAULT_MAX_BUFFER_SIZE = 256 * 1024; | ||
class WrappedResponse { | ||
constructor(httpResponse, responseBufferSize) { | ||
constructor(httpResponse) { | ||
httpResponse.pause(); | ||
this.responseBufferSize = responseBufferSize; | ||
this.statusCode = httpResponse.statusCode; | ||
@@ -25,2 +25,17 @@ | ||
/** | ||
* Returns an object with the response details in the standard format. | ||
* | ||
* The responseHandler should return this simplified object rather than | ||
* the WrappedResponse. | ||
*/ | ||
getStandardResponse(body) { | ||
return { | ||
statusCode: this.statusCode, | ||
headers: this.headers, | ||
getHeader: this.getHeader.bind(this), | ||
body | ||
}; | ||
} | ||
/** | ||
* Reads the response body and resolves with that buffer. | ||
@@ -30,4 +45,6 @@ * | ||
*/ | ||
bufferBody() { | ||
const max = this.responseBufferSize; | ||
bufferBody(maxSize) { | ||
if (maxSize === undefined) { | ||
maxSize = DEFAULT_MAX_BUFFER_SIZE; | ||
} | ||
const chunks = []; | ||
@@ -41,3 +58,3 @@ let byteCount = 0; | ||
this.httpResponse.on('data', (chunk) => { | ||
if (byteCount + chunk.length > max) { | ||
if (byteCount + chunk.length > maxSize) { | ||
return this.httpResponse.destroy(new Error('Overflow response body')); | ||
@@ -57,4 +74,4 @@ } | ||
*/ | ||
bufferJson() { | ||
return this.bufferBody() | ||
bufferJson(maxSize) { | ||
return this.bufferBody(maxSize) | ||
.then((buffer) => { | ||
@@ -61,0 +78,0 @@ if (buffer.length > 0) { |
{ | ||
"name": "httplease", | ||
"version": "0.3.2-beta2", | ||
"version": "0.4.0-beta1", | ||
"description": "HTTP client library with support for pluggable filters, including Zipkin, ASAP, etc", | ||
@@ -49,5 +49,4 @@ "main": "index.js", | ||
"jasmine-promise-tools": "^1.0.0", | ||
"proxyquire": "^1.7.4", | ||
"q": "^1.4.1" | ||
"proxyquire": "^1.7.4" | ||
} | ||
} |
@@ -50,3 +50,5 @@  | ||
.withExpectStatus([200, 204]) | ||
.withTimeout(10000); | ||
.withBufferJsonResponseHandler() | ||
.withTimeout(10000) | ||
.withAgentOptions({keepAlive: true}); | ||
@@ -87,2 +89,4 @@ | ||
httplease.builder() | ||
.withBufferJsonResponseHandler() | ||
.withExpectStatus([200]) | ||
.send({ | ||
@@ -107,2 +111,4 @@ baseUrl: 'http://example.com/resource', | ||
.withStreamBody(fs.createReadStream('bigdata.json')) | ||
.withDiscardBodyResponseHandler() | ||
.withExpectStatus([200]) | ||
.send() | ||
@@ -118,2 +124,3 @@ .then((response) => { | ||
.withPath('http://example.com/') | ||
.withExpectStatus([200]) | ||
.withResponseHandler((response) => response.pipe(process.stdout)) | ||
@@ -120,0 +127,0 @@ .send() |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
29572
8
684
184
2