PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/node_modules/less-middleware/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js

https://gitlab.com/mba811/webAudio
JavaScript | 236 lines | 193 code | 33 blank | 10 comment | 23 complexity | 68041d4074ddeb44f9797b0928c33e8d MD5 | raw file
Possible License(s): Apache-2.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, 0BSD
  1. 'use strict'
  2. var net = require('net')
  3. , tls = require('tls')
  4. , http = require('http')
  5. , https = require('https')
  6. , events = require('events')
  7. , assert = require('assert')
  8. , util = require('util')
  9. ;
  10. exports.httpOverHttp = httpOverHttp
  11. exports.httpsOverHttp = httpsOverHttp
  12. exports.httpOverHttps = httpOverHttps
  13. exports.httpsOverHttps = httpsOverHttps
  14. function httpOverHttp(options) {
  15. var agent = new TunnelingAgent(options)
  16. agent.request = http.request
  17. return agent
  18. }
  19. function httpsOverHttp(options) {
  20. var agent = new TunnelingAgent(options)
  21. agent.request = http.request
  22. agent.createSocket = createSecureSocket
  23. return agent
  24. }
  25. function httpOverHttps(options) {
  26. var agent = new TunnelingAgent(options)
  27. agent.request = https.request
  28. return agent
  29. }
  30. function httpsOverHttps(options) {
  31. var agent = new TunnelingAgent(options)
  32. agent.request = https.request
  33. agent.createSocket = createSecureSocket
  34. return agent
  35. }
  36. function TunnelingAgent(options) {
  37. var self = this
  38. self.options = options || {}
  39. self.proxyOptions = self.options.proxy || {}
  40. self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets
  41. self.requests = []
  42. self.sockets = []
  43. self.on('free', function onFree(socket, host, port) {
  44. for (var i = 0, len = self.requests.length; i < len; ++i) {
  45. var pending = self.requests[i]
  46. if (pending.host === host && pending.port === port) {
  47. // Detect the request to connect same origin server,
  48. // reuse the connection.
  49. self.requests.splice(i, 1)
  50. pending.request.onSocket(socket)
  51. return
  52. }
  53. }
  54. socket.destroy()
  55. self.removeSocket(socket)
  56. })
  57. }
  58. util.inherits(TunnelingAgent, events.EventEmitter)
  59. TunnelingAgent.prototype.addRequest = function addRequest(req, options) {
  60. var self = this
  61. // Legacy API: addRequest(req, host, port, path)
  62. if (typeof options === 'string') {
  63. options = {
  64. host: options,
  65. port: arguments[2],
  66. path: arguments[3]
  67. };
  68. }
  69. if (self.sockets.length >= this.maxSockets) {
  70. // We are over limit so we'll add it to the queue.
  71. self.requests.push({host: host, port: port, request: req})
  72. return
  73. }
  74. // If we are under maxSockets create a new one.
  75. self.createSocket({host: options.host, port: options.port, request: req}, function(socket) {
  76. socket.on('free', onFree)
  77. socket.on('close', onCloseOrRemove)
  78. socket.on('agentRemove', onCloseOrRemove)
  79. req.onSocket(socket)
  80. function onFree() {
  81. self.emit('free', socket, options.host, options.port)
  82. }
  83. function onCloseOrRemove(err) {
  84. self.removeSocket()
  85. socket.removeListener('free', onFree)
  86. socket.removeListener('close', onCloseOrRemove)
  87. socket.removeListener('agentRemove', onCloseOrRemove)
  88. }
  89. })
  90. }
  91. TunnelingAgent.prototype.createSocket = function createSocket(options, cb) {
  92. var self = this
  93. var placeholder = {}
  94. self.sockets.push(placeholder)
  95. var connectOptions = mergeOptions({}, self.proxyOptions,
  96. { method: 'CONNECT'
  97. , path: options.host + ':' + options.port
  98. , agent: false
  99. }
  100. )
  101. if (connectOptions.proxyAuth) {
  102. connectOptions.headers = connectOptions.headers || {}
  103. connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
  104. new Buffer(connectOptions.proxyAuth).toString('base64')
  105. }
  106. debug('making CONNECT request')
  107. var connectReq = self.request(connectOptions)
  108. connectReq.useChunkedEncodingByDefault = false // for v0.6
  109. connectReq.once('response', onResponse) // for v0.6
  110. connectReq.once('upgrade', onUpgrade) // for v0.6
  111. connectReq.once('connect', onConnect) // for v0.7 or later
  112. connectReq.once('error', onError)
  113. connectReq.end()
  114. function onResponse(res) {
  115. // Very hacky. This is necessary to avoid http-parser leaks.
  116. res.upgrade = true
  117. }
  118. function onUpgrade(res, socket, head) {
  119. // Hacky.
  120. process.nextTick(function() {
  121. onConnect(res, socket, head)
  122. })
  123. }
  124. function onConnect(res, socket, head) {
  125. connectReq.removeAllListeners()
  126. socket.removeAllListeners()
  127. if (res.statusCode === 200) {
  128. assert.equal(head.length, 0)
  129. debug('tunneling connection has established')
  130. self.sockets[self.sockets.indexOf(placeholder)] = socket
  131. cb(socket)
  132. } else {
  133. debug('tunneling socket could not be established, statusCode=%d', res.statusCode)
  134. var error = new Error('tunneling socket could not be established, ' + 'statusCode=' + res.statusCode)
  135. error.code = 'ECONNRESET'
  136. options.request.emit('error', error)
  137. self.removeSocket(placeholder)
  138. }
  139. }
  140. function onError(cause) {
  141. connectReq.removeAllListeners()
  142. debug('tunneling socket could not be established, cause=%s\n', cause.message, cause.stack)
  143. var error = new Error('tunneling socket could not be established, ' + 'cause=' + cause.message)
  144. error.code = 'ECONNRESET'
  145. options.request.emit('error', error)
  146. self.removeSocket(placeholder)
  147. }
  148. }
  149. TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
  150. var pos = this.sockets.indexOf(socket)
  151. if (pos === -1) return
  152. this.sockets.splice(pos, 1)
  153. var pending = this.requests.shift()
  154. if (pending) {
  155. // If we have pending requests and a socket gets closed a new one
  156. // needs to be created to take over in the pool for the one that closed.
  157. this.createSocket(pending, function(socket) {
  158. pending.request.onSocket(socket)
  159. })
  160. }
  161. }
  162. function createSecureSocket(options, cb) {
  163. var self = this
  164. TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
  165. // 0 is dummy port for v0.6
  166. var secureSocket = tls.connect(0, mergeOptions({}, self.options,
  167. { servername: options.host
  168. , socket: socket
  169. }
  170. ))
  171. cb(secureSocket)
  172. })
  173. }
  174. function mergeOptions(target) {
  175. for (var i = 1, len = arguments.length; i < len; ++i) {
  176. var overrides = arguments[i]
  177. if (typeof overrides === 'object') {
  178. var keys = Object.keys(overrides)
  179. for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
  180. var k = keys[j]
  181. if (overrides[k] !== undefined) {
  182. target[k] = overrides[k]
  183. }
  184. }
  185. }
  186. }
  187. return target
  188. }
  189. var debug
  190. if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
  191. debug = function() {
  192. var args = Array.prototype.slice.call(arguments)
  193. if (typeof args[0] === 'string') {
  194. args[0] = 'TUNNEL: ' + args[0]
  195. } else {
  196. args.unshift('TUNNEL:')
  197. }
  198. console.error.apply(console, args)
  199. }
  200. } else {
  201. debug = function() {}
  202. }
  203. exports.debug = debug // for test