"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/npm/node_modules/request/request.js" (7 Feb 2017, 40910 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 'use strict'
    2 
    3 var http = require('http')
    4   , https = require('https')
    5   , url = require('url')
    6   , util = require('util')
    7   , stream = require('stream')
    8   , zlib = require('zlib')
    9   , bl = require('bl')
   10   , hawk = require('hawk')
   11   , aws2 = require('aws-sign2')
   12   , httpSignature = require('http-signature')
   13   , mime = require('mime-types')
   14   , stringstream = require('stringstream')
   15   , caseless = require('caseless')
   16   , ForeverAgent = require('forever-agent')
   17   , FormData = require('form-data')
   18   , extend = require('extend')
   19   , isstream = require('isstream')
   20   , isTypedArray = require('is-typedarray').strict
   21   , helpers = require('./lib/helpers')
   22   , cookies = require('./lib/cookies')
   23   , getProxyFromURI = require('./lib/getProxyFromURI')
   24   , Querystring = require('./lib/querystring').Querystring
   25   , Har = require('./lib/har').Har
   26   , Auth = require('./lib/auth').Auth
   27   , OAuth = require('./lib/oauth').OAuth
   28   , Multipart = require('./lib/multipart').Multipart
   29   , Redirect = require('./lib/redirect').Redirect
   30   , Tunnel = require('./lib/tunnel').Tunnel
   31 
   32 var safeStringify = helpers.safeStringify
   33   , isReadStream = helpers.isReadStream
   34   , toBase64 = helpers.toBase64
   35   , defer = helpers.defer
   36   , copy = helpers.copy
   37   , version = helpers.version
   38   , globalCookieJar = cookies.jar()
   39 
   40 
   41 var globalPool = {}
   42 
   43 function filterForNonReserved(reserved, options) {
   44   // Filter out properties that are not reserved.
   45   // Reserved values are passed in at call site.
   46 
   47   var object = {}
   48   for (var i in options) {
   49     var notReserved = (reserved.indexOf(i) === -1)
   50     if (notReserved) {
   51       object[i] = options[i]
   52     }
   53   }
   54   return object
   55 }
   56 
   57 function filterOutReservedFunctions(reserved, options) {
   58   // Filter out properties that are functions and are reserved.
   59   // Reserved values are passed in at call site.
   60 
   61   var object = {}
   62   for (var i in options) {
   63     var isReserved = !(reserved.indexOf(i) === -1)
   64     var isFunction = (typeof options[i] === 'function')
   65     if (!(isReserved && isFunction)) {
   66       object[i] = options[i]
   67     }
   68   }
   69   return object
   70 
   71 }
   72 
   73 // Function for properly handling a connection error
   74 function connectionErrorHandler(error) {
   75   var socket = this
   76   if (socket.res) {
   77     if (socket.res.request) {
   78       socket.res.request.emit('error', error)
   79     } else {
   80       socket.res.emit('error', error)
   81     }
   82   } else {
   83     socket._httpMessage.emit('error', error)
   84   }
   85 }
   86 
   87 // Return a simpler request object to allow serialization
   88 function requestToJSON() {
   89   var self = this
   90   return {
   91     uri: self.uri,
   92     method: self.method,
   93     headers: self.headers
   94   }
   95 }
   96 
   97 // Return a simpler response object to allow serialization
   98 function responseToJSON() {
   99   var self = this
  100   return {
  101     statusCode: self.statusCode,
  102     body: self.body,
  103     headers: self.headers,
  104     request: requestToJSON.call(self.request)
  105   }
  106 }
  107 
  108 function Request (options) {
  109   // if given the method property in options, set property explicitMethod to true
  110 
  111   // extend the Request instance with any non-reserved properties
  112   // remove any reserved functions from the options object
  113   // set Request instance to be readable and writable
  114   // call init
  115 
  116   var self = this
  117 
  118   // start with HAR, then override with additional options
  119   if (options.har) {
  120     self._har = new Har(self)
  121     options = self._har.options(options)
  122   }
  123 
  124   stream.Stream.call(self)
  125   var reserved = Object.keys(Request.prototype)
  126   var nonReserved = filterForNonReserved(reserved, options)
  127 
  128   extend(self, nonReserved)
  129   options = filterOutReservedFunctions(reserved, options)
  130 
  131   self.readable = true
  132   self.writable = true
  133   if (options.method) {
  134     self.explicitMethod = true
  135   }
  136   self._qs = new Querystring(self)
  137   self._auth = new Auth(self)
  138   self._oauth = new OAuth(self)
  139   self._multipart = new Multipart(self)
  140   self._redirect = new Redirect(self)
  141   self._tunnel = new Tunnel(self)
  142   self.init(options)
  143 }
  144 
  145 util.inherits(Request, stream.Stream)
  146 
  147 // Debugging
  148 Request.debug = process.env.NODE_DEBUG && /\brequest\b/.test(process.env.NODE_DEBUG)
  149 function debug() {
  150   if (Request.debug) {
  151     console.error('REQUEST %s', util.format.apply(util, arguments))
  152   }
  153 }
  154 Request.prototype.debug = debug
  155 
  156 Request.prototype.init = function (options) {
  157   // init() contains all the code to setup the request object.
  158   // the actual outgoing request is not started until start() is called
  159   // this function is called from both the constructor and on redirect.
  160   var self = this
  161   if (!options) {
  162     options = {}
  163   }
  164   self.headers = self.headers ? copy(self.headers) : {}
  165 
  166   // Delete headers with value undefined since they break
  167   // ClientRequest.OutgoingMessage.setHeader in node 0.12
  168   for (var headerName in self.headers) {
  169     if (typeof self.headers[headerName] === 'undefined') {
  170       delete self.headers[headerName]
  171     }
  172   }
  173 
  174   caseless.httpify(self, self.headers)
  175 
  176   if (!self.method) {
  177     self.method = options.method || 'GET'
  178   }
  179   if (!self.localAddress) {
  180     self.localAddress = options.localAddress
  181   }
  182 
  183   self._qs.init(options)
  184 
  185   debug(options)
  186   if (!self.pool && self.pool !== false) {
  187     self.pool = globalPool
  188   }
  189   self.dests = self.dests || []
  190   self.__isRequestRequest = true
  191 
  192   // Protect against double callback
  193   if (!self._callback && self.callback) {
  194     self._callback = self.callback
  195     self.callback = function () {
  196       if (self._callbackCalled) {
  197         return // Print a warning maybe?
  198       }
  199       self._callbackCalled = true
  200       self._callback.apply(self, arguments)
  201     }
  202     self.on('error', self.callback.bind())
  203     self.on('complete', self.callback.bind(self, null))
  204   }
  205 
  206   // People use this property instead all the time, so support it
  207   if (!self.uri && self.url) {
  208     self.uri = self.url
  209     delete self.url
  210   }
  211 
  212   // If there's a baseUrl, then use it as the base URL (i.e. uri must be
  213   // specified as a relative path and is appended to baseUrl).
  214   if (self.baseUrl) {
  215     if (typeof self.baseUrl !== 'string') {
  216       return self.emit('error', new Error('options.baseUrl must be a string'))
  217     }
  218 
  219     if (typeof self.uri !== 'string') {
  220       return self.emit('error', new Error('options.uri must be a string when using options.baseUrl'))
  221     }
  222 
  223     if (self.uri.indexOf('//') === 0 || self.uri.indexOf('://') !== -1) {
  224       return self.emit('error', new Error('options.uri must be a path when using options.baseUrl'))
  225     }
  226 
  227     // Handle all cases to make sure that there's only one slash between
  228     // baseUrl and uri.
  229     var baseUrlEndsWithSlash = self.baseUrl.lastIndexOf('/') === self.baseUrl.length - 1
  230     var uriStartsWithSlash = self.uri.indexOf('/') === 0
  231 
  232     if (baseUrlEndsWithSlash && uriStartsWithSlash) {
  233       self.uri = self.baseUrl + self.uri.slice(1)
  234     } else if (baseUrlEndsWithSlash || uriStartsWithSlash) {
  235       self.uri = self.baseUrl + self.uri
  236     } else if (self.uri === '') {
  237       self.uri = self.baseUrl
  238     } else {
  239       self.uri = self.baseUrl + '/' + self.uri
  240     }
  241     delete self.baseUrl
  242   }
  243 
  244   // A URI is needed by this point, emit error if we haven't been able to get one
  245   if (!self.uri) {
  246     return self.emit('error', new Error('options.uri is a required argument'))
  247   }
  248 
  249   // If a string URI/URL was given, parse it into a URL object
  250   if (typeof self.uri === 'string') {
  251     self.uri = url.parse(self.uri)
  252   }
  253 
  254   // Some URL objects are not from a URL parsed string and need href added
  255   if (!self.uri.href) {
  256     self.uri.href = url.format(self.uri)
  257   }
  258 
  259   // DEPRECATED: Warning for users of the old Unix Sockets URL Scheme
  260   if (self.uri.protocol === 'unix:') {
  261     return self.emit('error', new Error('`unix://` URL scheme is no longer supported. Please use the format `http://unix:SOCKET:PATH`'))
  262   }
  263 
  264   // Support Unix Sockets
  265   if (self.uri.host === 'unix') {
  266     self.enableUnixSocket()
  267   }
  268 
  269   if (self.strictSSL === false) {
  270     self.rejectUnauthorized = false
  271   }
  272 
  273   if (!self.uri.pathname) {self.uri.pathname = '/'}
  274 
  275   if (!(self.uri.host || (self.uri.hostname && self.uri.port)) && !self.uri.isUnix) {
  276     // Invalid URI: it may generate lot of bad errors, like 'TypeError: Cannot call method `indexOf` of undefined' in CookieJar
  277     // Detect and reject it as soon as possible
  278     var faultyUri = url.format(self.uri)
  279     var message = 'Invalid URI "' + faultyUri + '"'
  280     if (Object.keys(options).length === 0) {
  281       // No option ? This can be the sign of a redirect
  282       // As this is a case where the user cannot do anything (they didn't call request directly with this URL)
  283       // they should be warned that it can be caused by a redirection (can save some hair)
  284       message += '. This can be caused by a crappy redirection.'
  285     }
  286     // This error was fatal
  287     self.abort()
  288     return self.emit('error', new Error(message))
  289   }
  290 
  291   if (!self.hasOwnProperty('proxy')) {
  292     self.proxy = getProxyFromURI(self.uri)
  293   }
  294 
  295   self.tunnel = self._tunnel.isEnabled()
  296   if (self.proxy) {
  297     self._tunnel.setup(options)
  298   }
  299 
  300   self._redirect.onRequest(options)
  301 
  302   self.setHost = false
  303   if (!self.hasHeader('host')) {
  304     var hostHeaderName = self.originalHostHeaderName || 'host'
  305     self.setHeader(hostHeaderName, self.uri.hostname)
  306     if (self.uri.port) {
  307       if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') &&
  308            !(self.uri.port === 443 && self.uri.protocol === 'https:') ) {
  309         self.setHeader(hostHeaderName, self.getHeader('host') + (':' + self.uri.port) )
  310       }
  311     }
  312     self.setHost = true
  313   }
  314 
  315   self.jar(self._jar || options.jar)
  316 
  317   if (!self.uri.port) {
  318     if (self.uri.protocol === 'http:') {self.uri.port = 80}
  319     else if (self.uri.protocol === 'https:') {self.uri.port = 443}
  320   }
  321 
  322   if (self.proxy && !self.tunnel) {
  323     self.port = self.proxy.port
  324     self.host = self.proxy.hostname
  325   } else {
  326     self.port = self.uri.port
  327     self.host = self.uri.hostname
  328   }
  329 
  330   if (options.form) {
  331     self.form(options.form)
  332   }
  333 
  334   if (options.formData) {
  335     var formData = options.formData
  336     var requestForm = self.form()
  337     var appendFormValue = function (key, value) {
  338       if (value.hasOwnProperty('value') && value.hasOwnProperty('options')) {
  339         requestForm.append(key, value.value, value.options)
  340       } else {
  341         requestForm.append(key, value)
  342       }
  343     }
  344     for (var formKey in formData) {
  345       if (formData.hasOwnProperty(formKey)) {
  346         var formValue = formData[formKey]
  347         if (formValue instanceof Array) {
  348           for (var j = 0; j < formValue.length; j++) {
  349             appendFormValue(formKey, formValue[j])
  350           }
  351         } else {
  352           appendFormValue(formKey, formValue)
  353         }
  354       }
  355     }
  356   }
  357 
  358   if (options.qs) {
  359     self.qs(options.qs)
  360   }
  361 
  362   if (self.uri.path) {
  363     self.path = self.uri.path
  364   } else {
  365     self.path = self.uri.pathname + (self.uri.search || '')
  366   }
  367 
  368   if (self.path.length === 0) {
  369     self.path = '/'
  370   }
  371 
  372   // Auth must happen last in case signing is dependent on other headers
  373   if (options.aws) {
  374     self.aws(options.aws)
  375   }
  376 
  377   if (options.hawk) {
  378     self.hawk(options.hawk)
  379   }
  380 
  381   if (options.httpSignature) {
  382     self.httpSignature(options.httpSignature)
  383   }
  384 
  385   if (options.auth) {
  386     if (Object.prototype.hasOwnProperty.call(options.auth, 'username')) {
  387       options.auth.user = options.auth.username
  388     }
  389     if (Object.prototype.hasOwnProperty.call(options.auth, 'password')) {
  390       options.auth.pass = options.auth.password
  391     }
  392 
  393     self.auth(
  394       options.auth.user,
  395       options.auth.pass,
  396       options.auth.sendImmediately,
  397       options.auth.bearer
  398     )
  399   }
  400 
  401   if (self.gzip && !self.hasHeader('accept-encoding')) {
  402     self.setHeader('accept-encoding', 'gzip, deflate')
  403   }
  404 
  405   if (self.uri.auth && !self.hasHeader('authorization')) {
  406     var uriAuthPieces = self.uri.auth.split(':').map(function(item) {return self._qs.unescape(item)})
  407     self.auth(uriAuthPieces[0], uriAuthPieces.slice(1).join(':'), true)
  408   }
  409 
  410   if (!self.tunnel && self.proxy && self.proxy.auth && !self.hasHeader('proxy-authorization')) {
  411     var proxyAuthPieces = self.proxy.auth.split(':').map(function(item) {return self._qs.unescape(item)})
  412     var authHeader = 'Basic ' + toBase64(proxyAuthPieces.join(':'))
  413     self.setHeader('proxy-authorization', authHeader)
  414   }
  415 
  416   if (self.proxy && !self.tunnel) {
  417     self.path = (self.uri.protocol + '//' + self.uri.host + self.path)
  418   }
  419 
  420   if (options.json) {
  421     self.json(options.json)
  422   }
  423   if (options.multipart) {
  424     self.multipart(options.multipart)
  425   }
  426 
  427   if (options.time) {
  428     self.timing = true
  429     self.elapsedTime = self.elapsedTime || 0
  430   }
  431 
  432   function setContentLength () {
  433     if (isTypedArray(self.body)) {
  434       self.body = new Buffer(self.body)
  435     }
  436 
  437     if (!self.hasHeader('content-length')) {
  438       var length
  439       if (typeof self.body === 'string') {
  440         length = Buffer.byteLength(self.body)
  441       }
  442       else if (Array.isArray(self.body)) {
  443         length = self.body.reduce(function (a, b) {return a + b.length}, 0)
  444       }
  445       else {
  446         length = self.body.length
  447       }
  448 
  449       if (length) {
  450         self.setHeader('content-length', length)
  451       } else {
  452         self.emit('error', new Error('Argument error, options.body.'))
  453       }
  454     }
  455   }
  456   if (self.body && !isstream(self.body)) {
  457     setContentLength()
  458   }
  459 
  460   if (options.oauth) {
  461     self.oauth(options.oauth)
  462   } else if (self._oauth.params && self.hasHeader('authorization')) {
  463     self.oauth(self._oauth.params)
  464   }
  465 
  466   var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol
  467     , defaultModules = {'http:':http, 'https:':https}
  468     , httpModules = self.httpModules || {}
  469 
  470   self.httpModule = httpModules[protocol] || defaultModules[protocol]
  471 
  472   if (!self.httpModule) {
  473     return self.emit('error', new Error('Invalid protocol: ' + protocol))
  474   }
  475 
  476   if (options.ca) {
  477     self.ca = options.ca
  478   }
  479 
  480   if (!self.agent) {
  481     if (options.agentOptions) {
  482       self.agentOptions = options.agentOptions
  483     }
  484 
  485     if (options.agentClass) {
  486       self.agentClass = options.agentClass
  487     } else if (options.forever) {
  488       var v = version()
  489       // use ForeverAgent in node 0.10- only
  490       if (v.major === 0 && v.minor <= 10) {
  491         self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL
  492       } else {
  493         self.agentClass = self.httpModule.Agent
  494         self.agentOptions = self.agentOptions || {}
  495         self.agentOptions.keepAlive = true
  496       }
  497     } else {
  498       self.agentClass = self.httpModule.Agent
  499     }
  500   }
  501 
  502   if (self.pool === false) {
  503     self.agent = false
  504   } else {
  505     self.agent = self.agent || self.getNewAgent()
  506   }
  507 
  508   self.on('pipe', function (src) {
  509     if (self.ntick && self._started) {
  510       self.emit('error', new Error('You cannot pipe to this stream after the outbound request has started.'))
  511     }
  512     self.src = src
  513     if (isReadStream(src)) {
  514       if (!self.hasHeader('content-type')) {
  515         self.setHeader('content-type', mime.lookup(src.path))
  516       }
  517     } else {
  518       if (src.headers) {
  519         for (var i in src.headers) {
  520           if (!self.hasHeader(i)) {
  521             self.setHeader(i, src.headers[i])
  522           }
  523         }
  524       }
  525       if (self._json && !self.hasHeader('content-type')) {
  526         self.setHeader('content-type', 'application/json')
  527       }
  528       if (src.method && !self.explicitMethod) {
  529         self.method = src.method
  530       }
  531     }
  532 
  533     // self.on('pipe', function () {
  534     //   console.error('You have already piped to this stream. Pipeing twice is likely to break the request.')
  535     // })
  536   })
  537 
  538   defer(function () {
  539     if (self._aborted) {
  540       return
  541     }
  542 
  543     var end = function () {
  544       if (self._form) {
  545         if (!self._auth.hasAuth) {
  546           self._form.pipe(self)
  547         }
  548         else if (self._auth.hasAuth && self._auth.sentAuth) {
  549           self._form.pipe(self)
  550         }
  551       }
  552       if (self._multipart && self._multipart.chunked) {
  553         self._multipart.body.pipe(self)
  554       }
  555       if (self.body) {
  556         if (isstream(self.body)) {
  557           self.body.pipe(self)
  558         } else {
  559           setContentLength()
  560           if (Array.isArray(self.body)) {
  561             self.body.forEach(function (part) {
  562               self.write(part)
  563             })
  564           } else {
  565             self.write(self.body)
  566           }
  567           self.end()
  568         }
  569       } else if (self.requestBodyStream) {
  570         console.warn('options.requestBodyStream is deprecated, please pass the request object to stream.pipe.')
  571         self.requestBodyStream.pipe(self)
  572       } else if (!self.src) {
  573         if (self._auth.hasAuth && !self._auth.sentAuth) {
  574           self.end()
  575           return
  576         }
  577         if (self.method !== 'GET' && typeof self.method !== 'undefined') {
  578           self.setHeader('content-length', 0)
  579         }
  580         self.end()
  581       }
  582     }
  583 
  584     if (self._form && !self.hasHeader('content-length')) {
  585       // Before ending the request, we had to compute the length of the whole form, asyncly
  586       self.setHeader(self._form.getHeaders(), true)
  587       self._form.getLength(function (err, length) {
  588         if (!err && !isNaN(length)) {
  589           self.setHeader('content-length', length)
  590         }
  591         end()
  592       })
  593     } else {
  594       end()
  595     }
  596 
  597     self.ntick = true
  598   })
  599 
  600 }
  601 
  602 Request.prototype.getNewAgent = function () {
  603   var self = this
  604   var Agent = self.agentClass
  605   var options = {}
  606   if (self.agentOptions) {
  607     for (var i in self.agentOptions) {
  608       options[i] = self.agentOptions[i]
  609     }
  610   }
  611   if (self.ca) {
  612     options.ca = self.ca
  613   }
  614   if (self.ciphers) {
  615     options.ciphers = self.ciphers
  616   }
  617   if (self.secureProtocol) {
  618     options.secureProtocol = self.secureProtocol
  619   }
  620   if (self.secureOptions) {
  621     options.secureOptions = self.secureOptions
  622   }
  623   if (typeof self.rejectUnauthorized !== 'undefined') {
  624     options.rejectUnauthorized = self.rejectUnauthorized
  625   }
  626 
  627   if (self.cert && self.key) {
  628     options.key = self.key
  629     options.cert = self.cert
  630   }
  631 
  632   if (self.pfx) {
  633     options.pfx = self.pfx
  634   }
  635 
  636   if (self.passphrase) {
  637     options.passphrase = self.passphrase
  638   }
  639 
  640   var poolKey = ''
  641 
  642   // different types of agents are in different pools
  643   if (Agent !== self.httpModule.Agent) {
  644     poolKey += Agent.name
  645   }
  646 
  647   // ca option is only relevant if proxy or destination are https
  648   var proxy = self.proxy
  649   if (typeof proxy === 'string') {
  650     proxy = url.parse(proxy)
  651   }
  652   var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:'
  653 
  654   if (isHttps) {
  655     if (options.ca) {
  656       if (poolKey) {
  657         poolKey += ':'
  658       }
  659       poolKey += options.ca
  660     }
  661 
  662     if (typeof options.rejectUnauthorized !== 'undefined') {
  663       if (poolKey) {
  664         poolKey += ':'
  665       }
  666       poolKey += options.rejectUnauthorized
  667     }
  668 
  669     if (options.cert) {
  670       if (poolKey) {
  671         poolKey += ':'
  672       }
  673       poolKey += options.cert.toString('ascii') + options.key.toString('ascii')
  674     }
  675 
  676     if (options.pfx) {
  677       if (poolKey) {
  678         poolKey += ':'
  679       }
  680       poolKey += options.pfx.toString('ascii')
  681     }
  682 
  683     if (options.ciphers) {
  684       if (poolKey) {
  685         poolKey += ':'
  686       }
  687       poolKey += options.ciphers
  688     }
  689 
  690     if (options.secureProtocol) {
  691       if (poolKey) {
  692         poolKey += ':'
  693       }
  694       poolKey += options.secureProtocol
  695     }
  696 
  697     if (options.secureOptions) {
  698       if (poolKey) {
  699         poolKey += ':'
  700       }
  701       poolKey += options.secureOptions
  702     }
  703   }
  704 
  705   if (self.pool === globalPool && !poolKey && Object.keys(options).length === 0 && self.httpModule.globalAgent) {
  706     // not doing anything special.  Use the globalAgent
  707     return self.httpModule.globalAgent
  708   }
  709 
  710   // we're using a stored agent.  Make sure it's protocol-specific
  711   poolKey = self.uri.protocol + poolKey
  712 
  713   // generate a new agent for this setting if none yet exists
  714   if (!self.pool[poolKey]) {
  715     self.pool[poolKey] = new Agent(options)
  716     // properly set maxSockets on new agents
  717     if (self.pool.maxSockets) {
  718       self.pool[poolKey].maxSockets = self.pool.maxSockets
  719     }
  720   }
  721 
  722   return self.pool[poolKey]
  723 }
  724 
  725 Request.prototype.start = function () {
  726   // start() is called once we are ready to send the outgoing HTTP request.
  727   // this is usually called on the first write(), end() or on nextTick()
  728   var self = this
  729 
  730   if (self._aborted) {
  731     return
  732   }
  733 
  734   self._started = true
  735   self.method = self.method || 'GET'
  736   self.href = self.uri.href
  737 
  738   if (self.src && self.src.stat && self.src.stat.size && !self.hasHeader('content-length')) {
  739     self.setHeader('content-length', self.src.stat.size)
  740   }
  741   if (self._aws) {
  742     self.aws(self._aws, true)
  743   }
  744 
  745   // We have a method named auth, which is completely different from the http.request
  746   // auth option.  If we don't remove it, we're gonna have a bad time.
  747   var reqOptions = copy(self)
  748   delete reqOptions.auth
  749 
  750   debug('make request', self.uri.href)
  751 
  752   try {
  753     self.req = self.httpModule.request(reqOptions)
  754   } catch (err) {
  755     self.emit('error', err)
  756     return
  757   }
  758 
  759   if (self.timing) {
  760     self.startTime = new Date().getTime()
  761   }
  762 
  763   if (self.timeout && !self.timeoutTimer) {
  764     var timeout = self.timeout < 0 ? 0 : self.timeout
  765     // Set a timeout in memory - this block will throw if the server takes more
  766     // than `timeout` to write the HTTP status and headers (corresponding to
  767     // the on('response') event on the client). NB: this measures wall-clock
  768     // time, not the time between bytes sent by the server.
  769     self.timeoutTimer = setTimeout(function () {
  770       var connectTimeout = self.req.socket && self.req.socket.readable === false
  771       self.abort()
  772       var e = new Error('ETIMEDOUT')
  773       e.code = 'ETIMEDOUT'
  774       e.connect = connectTimeout
  775       self.emit('error', e)
  776     }, timeout)
  777 
  778     if (self.req.setTimeout) { // only works on node 0.6+
  779       // Set an additional timeout on the socket, via the `setsockopt` syscall.
  780       // This timeout sets the amount of time to wait *between* bytes sent
  781       // from the server, and may or may not correspond to the wall-clock time
  782       // elapsed from the start of the request.
  783       //
  784       // In particular, it's useful for erroring if the server fails to send
  785       // data halfway through streaming a response.
  786       self.req.setTimeout(timeout, function () {
  787         if (self.req) {
  788           self.req.abort()
  789           var e = new Error('ESOCKETTIMEDOUT')
  790           e.code = 'ESOCKETTIMEDOUT'
  791           e.connect = false
  792           self.emit('error', e)
  793         }
  794       })
  795     }
  796   }
  797 
  798   self.req.on('response', self.onRequestResponse.bind(self))
  799   self.req.on('error', self.onRequestError.bind(self))
  800   self.req.on('drain', function() {
  801     self.emit('drain')
  802   })
  803   self.req.on('socket', function(socket) {
  804     self.emit('socket', socket)
  805   })
  806 
  807   self.on('end', function() {
  808     if ( self.req.connection ) {
  809       self.req.connection.removeListener('error', connectionErrorHandler)
  810     }
  811   })
  812   self.emit('request', self.req)
  813 }
  814 
  815 Request.prototype.onRequestError = function (error) {
  816   var self = this
  817   if (self._aborted) {
  818     return
  819   }
  820   if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET'
  821       && self.agent.addRequestNoreuse) {
  822     self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) }
  823     self.start()
  824     self.req.end()
  825     return
  826   }
  827   if (self.timeout && self.timeoutTimer) {
  828     clearTimeout(self.timeoutTimer)
  829     self.timeoutTimer = null
  830   }
  831   self.emit('error', error)
  832 }
  833 
  834 Request.prototype.onRequestResponse = function (response) {
  835   var self = this
  836   debug('onRequestResponse', self.uri.href, response.statusCode, response.headers)
  837   response.on('end', function() {
  838     if (self.timing) {
  839       self.elapsedTime += (new Date().getTime() - self.startTime)
  840       debug('elapsed time', self.elapsedTime)
  841       response.elapsedTime = self.elapsedTime
  842     }
  843     debug('response end', self.uri.href, response.statusCode, response.headers)
  844   })
  845 
  846   // The check on response.connection is a workaround for browserify.
  847   if (response.connection && response.connection.listeners('error').indexOf(connectionErrorHandler) === -1) {
  848     response.connection.setMaxListeners(0)
  849     response.connection.once('error', connectionErrorHandler)
  850   }
  851   if (self._aborted) {
  852     debug('aborted', self.uri.href)
  853     response.resume()
  854     return
  855   }
  856 
  857   self.response = response
  858   response.request = self
  859   response.toJSON = responseToJSON
  860 
  861   // XXX This is different on 0.10, because SSL is strict by default
  862   if (self.httpModule === https &&
  863       self.strictSSL && (!response.hasOwnProperty('socket') ||
  864       !response.socket.authorized)) {
  865     debug('strict ssl error', self.uri.href)
  866     var sslErr = response.hasOwnProperty('socket') ? response.socket.authorizationError : self.uri.href + ' does not support SSL'
  867     self.emit('error', new Error('SSL Error: ' + sslErr))
  868     return
  869   }
  870 
  871   // Save the original host before any redirect (if it changes, we need to
  872   // remove any authorization headers).  Also remember the case of the header
  873   // name because lots of broken servers expect Host instead of host and we
  874   // want the caller to be able to specify this.
  875   self.originalHost = self.getHeader('host')
  876   if (!self.originalHostHeaderName) {
  877     self.originalHostHeaderName = self.hasHeader('host')
  878   }
  879   if (self.setHost) {
  880     self.removeHeader('host')
  881   }
  882   if (self.timeout && self.timeoutTimer) {
  883     clearTimeout(self.timeoutTimer)
  884     self.timeoutTimer = null
  885   }
  886 
  887   var targetCookieJar = (self._jar && self._jar.setCookie) ? self._jar : globalCookieJar
  888   var addCookie = function (cookie) {
  889     //set the cookie if it's domain in the href's domain.
  890     try {
  891       targetCookieJar.setCookie(cookie, self.uri.href, {ignoreError: true})
  892     } catch (e) {
  893       self.emit('error', e)
  894     }
  895   }
  896 
  897   response.caseless = caseless(response.headers)
  898 
  899   if (response.caseless.has('set-cookie') && (!self._disableCookies)) {
  900     var headerName = response.caseless.has('set-cookie')
  901     if (Array.isArray(response.headers[headerName])) {
  902       response.headers[headerName].forEach(addCookie)
  903     } else {
  904       addCookie(response.headers[headerName])
  905     }
  906   }
  907 
  908   if (self._redirect.onResponse(response)) {
  909     return // Ignore the rest of the response
  910   } else {
  911     // Be a good stream and emit end when the response is finished.
  912     // Hack to emit end on close because of a core bug that never fires end
  913     response.on('close', function () {
  914       if (!self._ended) {
  915         self.response.emit('end')
  916       }
  917     })
  918 
  919     response.on('end', function () {
  920       self._ended = true
  921     })
  922 
  923     var noBody = function (code) {
  924       return (
  925         self.method === 'HEAD'
  926         // Informational
  927         || (code >= 100 && code < 200)
  928         // No Content
  929         || code === 204
  930         // Not Modified
  931         || code === 304
  932       )
  933     }
  934 
  935     var responseContent
  936     if (self.gzip && !noBody(response.statusCode)) {
  937       var contentEncoding = response.headers['content-encoding'] || 'identity'
  938       contentEncoding = contentEncoding.trim().toLowerCase()
  939 
  940       if (contentEncoding === 'gzip') {
  941         responseContent = zlib.createGunzip()
  942         response.pipe(responseContent)
  943       } else if (contentEncoding === 'deflate') {
  944         responseContent = zlib.createInflate()
  945         response.pipe(responseContent)
  946       } else {
  947         // Since previous versions didn't check for Content-Encoding header,
  948         // ignore any invalid values to preserve backwards-compatibility
  949         if (contentEncoding !== 'identity') {
  950           debug('ignoring unrecognized Content-Encoding ' + contentEncoding)
  951         }
  952         responseContent = response
  953       }
  954     } else {
  955       responseContent = response
  956     }
  957 
  958     if (self.encoding) {
  959       if (self.dests.length !== 0) {
  960         console.error('Ignoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.')
  961       } else if (responseContent.setEncoding) {
  962         responseContent.setEncoding(self.encoding)
  963       } else {
  964         // Should only occur on node pre-v0.9.4 (joyent/node@9b5abe5) with
  965         // zlib streams.
  966         // If/When support for 0.9.4 is dropped, this should be unnecessary.
  967         responseContent = responseContent.pipe(stringstream(self.encoding))
  968       }
  969     }
  970 
  971     if (self._paused) {
  972       responseContent.pause()
  973     }
  974 
  975     self.responseContent = responseContent
  976 
  977     self.emit('response', response)
  978 
  979     self.dests.forEach(function (dest) {
  980       self.pipeDest(dest)
  981     })
  982 
  983     responseContent.on('data', function (chunk) {
  984       self._destdata = true
  985       self.emit('data', chunk)
  986     })
  987     responseContent.on('end', function (chunk) {
  988       self.emit('end', chunk)
  989     })
  990     responseContent.on('error', function (error) {
  991       self.emit('error', error)
  992     })
  993     responseContent.on('close', function () {self.emit('close')})
  994 
  995     if (self.callback) {
  996       self.readResponseBody(response)
  997     }
  998     //if no callback
  999     else {
 1000       self.on('end', function () {
 1001         if (self._aborted) {
 1002           debug('aborted', self.uri.href)
 1003           return
 1004         }
 1005         self.emit('complete', response)
 1006       })
 1007     }
 1008   }
 1009   debug('finish init function', self.uri.href)
 1010 }
 1011 
 1012 Request.prototype.readResponseBody = function (response) {
 1013   var self = this
 1014   debug('reading response\'s body')
 1015   var buffer = bl()
 1016     , strings = []
 1017 
 1018   self.on('data', function (chunk) {
 1019     if (Buffer.isBuffer(chunk)) {
 1020       buffer.append(chunk)
 1021     } else {
 1022       strings.push(chunk)
 1023     }
 1024   })
 1025   self.on('end', function () {
 1026     debug('end event', self.uri.href)
 1027     if (self._aborted) {
 1028       debug('aborted', self.uri.href)
 1029       // `buffer` is defined in the parent scope and used in a closure it exists for the life of the request.
 1030       // This can lead to leaky behavior if the user retains a reference to the request object.
 1031       buffer.destroy()
 1032       return
 1033     }
 1034 
 1035     if (buffer.length) {
 1036       debug('has body', self.uri.href, buffer.length)
 1037       if (self.encoding === null) {
 1038         // response.body = buffer
 1039         // can't move to this until https://github.com/rvagg/bl/issues/13
 1040         response.body = buffer.slice()
 1041       } else {
 1042         response.body = buffer.toString(self.encoding)
 1043       }
 1044       // `buffer` is defined in the parent scope and used in a closure it exists for the life of the Request.
 1045       // This can lead to leaky behavior if the user retains a reference to the request object.
 1046       buffer.destroy()
 1047     } else if (strings.length) {
 1048       // The UTF8 BOM [0xEF,0xBB,0xBF] is converted to [0xFE,0xFF] in the JS UTC16/UCS2 representation.
 1049       // Strip this value out when the encoding is set to 'utf8', as upstream consumers won't expect it and it breaks JSON.parse().
 1050       if (self.encoding === 'utf8' && strings[0].length > 0 && strings[0][0] === '\uFEFF') {
 1051         strings[0] = strings[0].substring(1)
 1052       }
 1053       response.body = strings.join('')
 1054     }
 1055 
 1056     if (self._json) {
 1057       try {
 1058         response.body = JSON.parse(response.body, self._jsonReviver)
 1059       } catch (e) {
 1060         debug('invalid JSON received', self.uri.href)
 1061       }
 1062     }
 1063     debug('emitting complete', self.uri.href)
 1064     if (typeof response.body === 'undefined' && !self._json) {
 1065       response.body = self.encoding === null ? new Buffer(0) : ''
 1066     }
 1067     self.emit('complete', response, response.body)
 1068   })
 1069 }
 1070 
 1071 Request.prototype.abort = function () {
 1072   var self = this
 1073   self._aborted = true
 1074 
 1075   if (self.req) {
 1076     self.req.abort()
 1077   }
 1078   else if (self.response) {
 1079     self.response.destroy()
 1080   }
 1081 
 1082   self.emit('abort')
 1083 }
 1084 
 1085 Request.prototype.pipeDest = function (dest) {
 1086   var self = this
 1087   var response = self.response
 1088   // Called after the response is received
 1089   if (dest.headers && !dest.headersSent) {
 1090     if (response.caseless.has('content-type')) {
 1091       var ctname = response.caseless.has('content-type')
 1092       if (dest.setHeader) {
 1093         dest.setHeader(ctname, response.headers[ctname])
 1094       }
 1095       else {
 1096         dest.headers[ctname] = response.headers[ctname]
 1097       }
 1098     }
 1099 
 1100     if (response.caseless.has('content-length')) {
 1101       var clname = response.caseless.has('content-length')
 1102       if (dest.setHeader) {
 1103         dest.setHeader(clname, response.headers[clname])
 1104       } else {
 1105         dest.headers[clname] = response.headers[clname]
 1106       }
 1107     }
 1108   }
 1109   if (dest.setHeader && !dest.headersSent) {
 1110     for (var i in response.headers) {
 1111       // If the response content is being decoded, the Content-Encoding header
 1112       // of the response doesn't represent the piped content, so don't pass it.
 1113       if (!self.gzip || i !== 'content-encoding') {
 1114         dest.setHeader(i, response.headers[i])
 1115       }
 1116     }
 1117     dest.statusCode = response.statusCode
 1118   }
 1119   if (self.pipefilter) {
 1120     self.pipefilter(response, dest)
 1121   }
 1122 }
 1123 
 1124 Request.prototype.qs = function (q, clobber) {
 1125   var self = this
 1126   var base
 1127   if (!clobber && self.uri.query) {
 1128     base = self._qs.parse(self.uri.query)
 1129   } else {
 1130     base = {}
 1131   }
 1132 
 1133   for (var i in q) {
 1134     base[i] = q[i]
 1135   }
 1136 
 1137   var qs = self._qs.stringify(base)
 1138 
 1139   if (qs === '') {
 1140     return self
 1141   }
 1142 
 1143   self.uri = url.parse(self.uri.href.split('?')[0] + '?' + qs)
 1144   self.url = self.uri
 1145   self.path = self.uri.path
 1146 
 1147   if (self.uri.host === 'unix') {
 1148     self.enableUnixSocket()
 1149   }
 1150 
 1151   return self
 1152 }
 1153 Request.prototype.form = function (form) {
 1154   var self = this
 1155   if (form) {
 1156     if (!/^application\/x-www-form-urlencoded\b/.test(self.getHeader('content-type'))) {
 1157       self.setHeader('content-type', 'application/x-www-form-urlencoded')
 1158     }
 1159     self.body = (typeof form === 'string')
 1160       ? self._qs.rfc3986(form.toString('utf8'))
 1161       : self._qs.stringify(form).toString('utf8')
 1162     return self
 1163   }
 1164   // create form-data object
 1165   self._form = new FormData()
 1166   self._form.on('error', function(err) {
 1167     err.message = 'form-data: ' + err.message
 1168     self.emit('error', err)
 1169     self.abort()
 1170   })
 1171   return self._form
 1172 }
 1173 Request.prototype.multipart = function (multipart) {
 1174   var self = this
 1175 
 1176   self._multipart.onRequest(multipart)
 1177 
 1178   if (!self._multipart.chunked) {
 1179     self.body = self._multipart.body
 1180   }
 1181 
 1182   return self
 1183 }
 1184 Request.prototype.json = function (val) {
 1185   var self = this
 1186 
 1187   if (!self.hasHeader('accept')) {
 1188     self.setHeader('accept', 'application/json')
 1189   }
 1190 
 1191   if (typeof self.jsonReplacer === 'function') {
 1192     self._jsonReplacer = self.jsonReplacer
 1193   }
 1194 
 1195   self._json = true
 1196   if (typeof val === 'boolean') {
 1197     if (self.body !== undefined) {
 1198       if (!/^application\/x-www-form-urlencoded\b/.test(self.getHeader('content-type'))) {
 1199         self.body = safeStringify(self.body, self._jsonReplacer)
 1200       } else {
 1201         self.body = self._qs.rfc3986(self.body)
 1202       }
 1203       if (!self.hasHeader('content-type')) {
 1204         self.setHeader('content-type', 'application/json')
 1205       }
 1206     }
 1207   } else {
 1208     self.body = safeStringify(val, self._jsonReplacer)
 1209     if (!self.hasHeader('content-type')) {
 1210       self.setHeader('content-type', 'application/json')
 1211     }
 1212   }
 1213 
 1214   if (typeof self.jsonReviver === 'function') {
 1215     self._jsonReviver = self.jsonReviver
 1216   }
 1217 
 1218   return self
 1219 }
 1220 Request.prototype.getHeader = function (name, headers) {
 1221   var self = this
 1222   var result, re, match
 1223   if (!headers) {
 1224     headers = self.headers
 1225   }
 1226   Object.keys(headers).forEach(function (key) {
 1227     if (key.length !== name.length) {
 1228       return
 1229     }
 1230     re = new RegExp(name, 'i')
 1231     match = key.match(re)
 1232     if (match) {
 1233       result = headers[key]
 1234     }
 1235   })
 1236   return result
 1237 }
 1238 Request.prototype.enableUnixSocket = function () {
 1239   // Get the socket & request paths from the URL
 1240   var unixParts = this.uri.path.split(':')
 1241     , host = unixParts[0]
 1242     , path = unixParts[1]
 1243   // Apply unix properties to request
 1244   this.socketPath = host
 1245   this.uri.pathname = path
 1246   this.uri.path = path
 1247   this.uri.host = host
 1248   this.uri.hostname = host
 1249   this.uri.isUnix = true
 1250 }
 1251 
 1252 
 1253 Request.prototype.auth = function (user, pass, sendImmediately, bearer) {
 1254   var self = this
 1255 
 1256   self._auth.onRequest(user, pass, sendImmediately, bearer)
 1257 
 1258   return self
 1259 }
 1260 Request.prototype.aws = function (opts, now) {
 1261   var self = this
 1262 
 1263   if (!now) {
 1264     self._aws = opts
 1265     return self
 1266   }
 1267   
 1268   if (opts.sign_version == 4 || opts.sign_version == '4') {
 1269     var aws4 = require('aws4')
 1270     // use aws4  
 1271     var options = {
 1272       host: self.uri.host,
 1273       path: self.uri.path,
 1274       method: self.method,
 1275       headers: {
 1276         'content-type': self.getHeader('content-type') || ''
 1277       },
 1278       body: self.body
 1279     }
 1280     var signRes = aws4.sign(options, {
 1281       accessKeyId: opts.key,
 1282       secretAccessKey: opts.secret
 1283     })
 1284     self.setHeader('authorization', signRes.headers.Authorization)
 1285     self.setHeader('x-amz-date', signRes.headers['X-Amz-Date'])
 1286   }
 1287   else {
 1288     // default: use aws-sign2
 1289     var date = new Date()
 1290     self.setHeader('date', date.toUTCString())
 1291     var auth =
 1292       { key: opts.key
 1293       , secret: opts.secret
 1294       , verb: self.method.toUpperCase()
 1295       , date: date
 1296       , contentType: self.getHeader('content-type') || ''
 1297       , md5: self.getHeader('content-md5') || ''
 1298       , amazonHeaders: aws2.canonicalizeHeaders(self.headers)
 1299       }
 1300     var path = self.uri.path
 1301     if (opts.bucket && path) {
 1302       auth.resource = '/' + opts.bucket + path
 1303     } else if (opts.bucket && !path) {
 1304       auth.resource = '/' + opts.bucket
 1305     } else if (!opts.bucket && path) {
 1306       auth.resource = path
 1307     } else if (!opts.bucket && !path) {
 1308       auth.resource = '/'
 1309     }
 1310     auth.resource = aws2.canonicalizeResource(auth.resource)
 1311     self.setHeader('authorization', aws2.authorization(auth))
 1312   }
 1313 
 1314   return self
 1315 }
 1316 Request.prototype.httpSignature = function (opts) {
 1317   var self = this
 1318   httpSignature.signRequest({
 1319     getHeader: function(header) {
 1320       return self.getHeader(header, self.headers)
 1321     },
 1322     setHeader: function(header, value) {
 1323       self.setHeader(header, value)
 1324     },
 1325     method: self.method,
 1326     path: self.path
 1327   }, opts)
 1328   debug('httpSignature authorization', self.getHeader('authorization'))
 1329 
 1330   return self
 1331 }
 1332 Request.prototype.hawk = function (opts) {
 1333   var self = this
 1334   self.setHeader('Authorization', hawk.client.header(self.uri, self.method, opts).field)
 1335 }
 1336 Request.prototype.oauth = function (_oauth) {
 1337   var self = this
 1338 
 1339   self._oauth.onRequest(_oauth)
 1340 
 1341   return self
 1342 }
 1343 
 1344 Request.prototype.jar = function (jar) {
 1345   var self = this
 1346   var cookies
 1347 
 1348   if (self._redirect.redirectsFollowed === 0) {
 1349     self.originalCookieHeader = self.getHeader('cookie')
 1350   }
 1351 
 1352   if (!jar) {
 1353     // disable cookies
 1354     cookies = false
 1355     self._disableCookies = true
 1356   } else {
 1357     var targetCookieJar = (jar && jar.getCookieString) ? jar : globalCookieJar
 1358     var urihref = self.uri.href
 1359     //fetch cookie in the Specified host
 1360     if (targetCookieJar) {
 1361       cookies = targetCookieJar.getCookieString(urihref)
 1362     }
 1363   }
 1364 
 1365   //if need cookie and cookie is not empty
 1366   if (cookies && cookies.length) {
 1367     if (self.originalCookieHeader) {
 1368       // Don't overwrite existing Cookie header
 1369       self.setHeader('cookie', self.originalCookieHeader + '; ' + cookies)
 1370     } else {
 1371       self.setHeader('cookie', cookies)
 1372     }
 1373   }
 1374   self._jar = jar
 1375   return self
 1376 }
 1377 
 1378 
 1379 // Stream API
 1380 Request.prototype.pipe = function (dest, opts) {
 1381   var self = this
 1382 
 1383   if (self.response) {
 1384     if (self._destdata) {
 1385       self.emit('error', new Error('You cannot pipe after data has been emitted from the response.'))
 1386     } else if (self._ended) {
 1387       self.emit('error', new Error('You cannot pipe after the response has been ended.'))
 1388     } else {
 1389       stream.Stream.prototype.pipe.call(self, dest, opts)
 1390       self.pipeDest(dest)
 1391       return dest
 1392     }
 1393   } else {
 1394     self.dests.push(dest)
 1395     stream.Stream.prototype.pipe.call(self, dest, opts)
 1396     return dest
 1397   }
 1398 }
 1399 Request.prototype.write = function () {
 1400   var self = this
 1401   if (self._aborted) {return}
 1402 
 1403   if (!self._started) {
 1404     self.start()
 1405   }
 1406   if (self.req) {
 1407     return self.req.write.apply(self.req, arguments)
 1408   }
 1409 }
 1410 Request.prototype.end = function (chunk) {
 1411   var self = this
 1412   if (self._aborted) {return}
 1413 
 1414   if (chunk) {
 1415     self.write(chunk)
 1416   }
 1417   if (!self._started) {
 1418     self.start()
 1419   }
 1420   if (self.req) {
 1421     self.req.end()
 1422   }
 1423 }
 1424 Request.prototype.pause = function () {
 1425   var self = this
 1426   if (!self.responseContent) {
 1427     self._paused = true
 1428   } else {
 1429     self.responseContent.pause.apply(self.responseContent, arguments)
 1430   }
 1431 }
 1432 Request.prototype.resume = function () {
 1433   var self = this
 1434   if (!self.responseContent) {
 1435     self._paused = false
 1436   } else {
 1437     self.responseContent.resume.apply(self.responseContent, arguments)
 1438   }
 1439 }
 1440 Request.prototype.destroy = function () {
 1441   var self = this
 1442   if (!self._ended) {
 1443     self.end()
 1444   } else if (self.response) {
 1445     self.response.destroy()
 1446   }
 1447 }
 1448 
 1449 Request.defaultProxyHeaderWhiteList =
 1450   Tunnel.defaultProxyHeaderWhiteList.slice()
 1451 
 1452 Request.defaultProxyHeaderExclusiveList =
 1453   Tunnel.defaultProxyHeaderExclusiveList.slice()
 1454 
 1455 // Exports
 1456 
 1457 Request.prototype.toJSON = requestToJSON
 1458 module.exports = Request