summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/request/request.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/node_modules/request/request.js')
-rw-r--r--deps/npm/node_modules/request/request.js123
1 files changed, 80 insertions, 43 deletions
diff --git a/deps/npm/node_modules/request/request.js b/deps/npm/node_modules/request/request.js
index 96a71b6ed5..26f70c2084 100644
--- a/deps/npm/node_modules/request/request.js
+++ b/deps/npm/node_modules/request/request.js
@@ -6,7 +6,6 @@ var http = require('http')
, util = require('util')
, stream = require('stream')
, zlib = require('zlib')
- , bl = require('bl')
, hawk = require('hawk')
, aws2 = require('aws-sign2')
, aws4 = require('aws4')
@@ -736,6 +735,11 @@ Request.prototype.start = function () {
debug('make request', self.uri.href)
+ // node v6.8.0 now supports a `timeout` value in `http.request()`, but we
+ // should delete it for now since we handle timeouts manually for better
+ // consistency with node versions before v6.8.0
+ delete reqOptions.timeout
+
try {
self.req = self.httpModule.request(reqOptions)
} catch (err) {
@@ -747,32 +751,30 @@ Request.prototype.start = function () {
self.startTime = new Date().getTime()
}
+ var timeout
if (self.timeout && !self.timeoutTimer) {
- var timeout = self.timeout < 0 ? 0 : self.timeout
- // Set a timeout in memory - this block will throw if the server takes more
- // than `timeout` to write the HTTP status and headers (corresponding to
- // the on('response') event on the client). NB: this measures wall-clock
- // time, not the time between bytes sent by the server.
- self.timeoutTimer = setTimeout(function () {
- var connectTimeout = self.req.socket && self.req.socket.readable === false
- self.abort()
- var e = new Error('ETIMEDOUT')
- e.code = 'ETIMEDOUT'
- e.connect = connectTimeout
- self.emit('error', e)
- }, timeout)
+ if (self.timeout < 0) {
+ timeout = 0
+ } else if (typeof self.timeout === 'number' && isFinite(self.timeout)) {
+ timeout = self.timeout
+ }
+ }
- if (self.req.setTimeout) { // only works on node 0.6+
- // Set an additional timeout on the socket, via the `setsockopt` syscall.
+ self.req.on('response', self.onRequestResponse.bind(self))
+ self.req.on('error', self.onRequestError.bind(self))
+ self.req.on('drain', function() {
+ self.emit('drain')
+ })
+ self.req.on('socket', function(socket) {
+ var setReqTimeout = function() {
// This timeout sets the amount of time to wait *between* bytes sent
- // from the server, and may or may not correspond to the wall-clock time
- // elapsed from the start of the request.
+ // from the server once connected.
//
// In particular, it's useful for erroring if the server fails to send
// data halfway through streaming a response.
self.req.setTimeout(timeout, function () {
if (self.req) {
- self.req.abort()
+ self.abort()
var e = new Error('ESOCKETTIMEDOUT')
e.code = 'ESOCKETTIMEDOUT'
e.connect = false
@@ -780,14 +782,44 @@ Request.prototype.start = function () {
}
})
}
- }
+ // `._connecting` was the old property which was made public in node v6.1.0
+ var isConnecting = socket._connecting || socket.connecting
+ if (timeout !== undefined) {
+ // Only start the connection timer if we're actually connecting a new
+ // socket, otherwise if we're already connected (because this is a
+ // keep-alive connection) do not bother. This is important since we won't
+ // get a 'connect' event for an already connected socket.
+ if (isConnecting) {
+ var onReqSockConnect = function() {
+ socket.removeListener('connect', onReqSockConnect)
+ clearTimeout(self.timeoutTimer)
+ self.timeoutTimer = null
+ setReqTimeout()
+ }
- self.req.on('response', self.onRequestResponse.bind(self))
- self.req.on('error', self.onRequestError.bind(self))
- self.req.on('drain', function() {
- self.emit('drain')
- })
- self.req.on('socket', function(socket) {
+ socket.on('connect', onReqSockConnect)
+
+ self.req.on('error', function(err) {
+ socket.removeListener('connect', onReqSockConnect)
+ })
+
+ // Set a timeout in memory - this block will throw if the server takes more
+ // than `timeout` to write the HTTP status and headers (corresponding to
+ // the on('response') event on the client). NB: this measures wall-clock
+ // time, not the time between bytes sent by the server.
+ self.timeoutTimer = setTimeout(function () {
+ socket.removeListener('connect', onReqSockConnect)
+ self.abort()
+ var e = new Error('ETIMEDOUT')
+ e.code = 'ETIMEDOUT'
+ e.connect = true
+ self.emit('error', e)
+ }, timeout)
+ } else {
+ // We're already connected
+ setReqTimeout()
+ }
+ }
self.emit('socket', socket)
})
@@ -893,7 +925,7 @@ Request.prototype.onRequestResponse = function (response) {
}
})
- response.on('end', function () {
+ response.once('end', function () {
self._ended = true
})
@@ -965,7 +997,7 @@ Request.prototype.onRequestResponse = function (response) {
self._destdata = true
self.emit('data', chunk)
})
- responseContent.on('end', function (chunk) {
+ responseContent.once('end', function (chunk) {
self.emit('end', chunk)
})
responseContent.on('error', function (error) {
@@ -993,14 +1025,16 @@ Request.prototype.onRequestResponse = function (response) {
Request.prototype.readResponseBody = function (response) {
var self = this
debug('reading response\'s body')
- var buffer = bl()
+ var buffers = []
+ , bufferLength = 0
, strings = []
self.on('data', function (chunk) {
- if (Buffer.isBuffer(chunk)) {
- buffer.append(chunk)
- } else {
+ if (!Buffer.isBuffer(chunk)) {
strings.push(chunk)
+ } else if (chunk.length) {
+ bufferLength += chunk.length
+ buffers.push(chunk)
}
})
self.on('end', function () {
@@ -1009,22 +1043,21 @@ Request.prototype.readResponseBody = function (response) {
debug('aborted', self.uri.href)
// `buffer` is defined in the parent scope and used in a closure it exists for the life of the request.
// This can lead to leaky behavior if the user retains a reference to the request object.
- buffer.destroy()
+ buffers = []
+ bufferLength = 0
return
}
- if (buffer.length) {
- debug('has body', self.uri.href, buffer.length)
- if (self.encoding === null) {
- // response.body = buffer
- // can't move to this until https://github.com/rvagg/bl/issues/13
- response.body = buffer.slice()
- } else {
- response.body = buffer.toString(self.encoding)
+ if (bufferLength) {
+ debug('has body', self.uri.href, bufferLength)
+ response.body = Buffer.concat(buffers, bufferLength)
+ if (self.encoding !== null) {
+ response.body = response.body.toString(self.encoding)
}
// `buffer` is defined in the parent scope and used in a closure it exists for the life of the Request.
// This can lead to leaky behavior if the user retains a reference to the request object.
- buffer.destroy()
+ buffers = []
+ bufferLength = 0
} else if (strings.length) {
// The UTF8 BOM [0xEF,0xBB,0xBF] is converted to [0xFE,0xFF] in the JS UTC16/UCS2 representation.
// Strip this value out when the encoding is set to 'utf8', as upstream consumers won't expect it and it breaks JSON.parse().
@@ -1259,10 +1292,14 @@ Request.prototype.aws = function (opts, now) {
}
var signRes = aws4.sign(options, {
accessKeyId: opts.key,
- secretAccessKey: opts.secret
+ secretAccessKey: opts.secret,
+ sessionToken: opts.session
})
self.setHeader('authorization', signRes.headers.Authorization)
self.setHeader('x-amz-date', signRes.headers['X-Amz-Date'])
+ if (signRes.headers['X-Amz-Security-Token']) {
+ self.setHeader('x-amz-security-token', signRes.headers['X-Amz-Security-Token'])
+ }
}
else {
// default: use aws-sign2