Guest User

Untitled

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