massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-json / node_modules / agent-base / index.js
1 'use strict';
2 require('./patch-core');
3 const inherits = require('util').inherits;
4 const promisify = require('es6-promisify');
5 const EventEmitter = require('events').EventEmitter;
6
7 module.exports = Agent;
8
9 function isAgent(v) {
10   return v && typeof v.addRequest === 'function';
11 }
12
13 /**
14  * Base `http.Agent` implementation.
15  * No pooling/keep-alive is implemented by default.
16  *
17  * @param {Function} callback
18  * @api public
19  */
20 function Agent(callback, _opts) {
21   if (!(this instanceof Agent)) {
22     return new Agent(callback, _opts);
23   }
24
25   EventEmitter.call(this);
26
27   // The callback gets promisified if it has 3 parameters
28   // (i.e. it has a callback function) lazily
29   this._promisifiedCallback = false;
30
31   let opts = _opts;
32   if ('function' === typeof callback) {
33     this.callback = callback;
34   } else if (callback) {
35     opts = callback;
36   }
37
38   // timeout for the socket to be returned from the callback
39   this.timeout = (opts && opts.timeout) || null;
40
41   this.options = opts;
42 }
43 inherits(Agent, EventEmitter);
44
45 /**
46  * Override this function in your subclass!
47  */
48 Agent.prototype.callback = function callback(req, opts) {
49   throw new Error(
50     '"agent-base" has no default implementation, you must subclass and override `callback()`'
51   );
52 };
53
54 /**
55  * Called by node-core's "_http_client.js" module when creating
56  * a new HTTP request with this Agent instance.
57  *
58  * @api public
59  */
60 Agent.prototype.addRequest = function addRequest(req, _opts) {
61   const ownOpts = Object.assign({}, _opts);
62
63   // Set default `host` for HTTP to localhost
64   if (null == ownOpts.host) {
65     ownOpts.host = 'localhost';
66   }
67
68   // Set default `port` for HTTP if none was explicitly specified
69   if (null == ownOpts.port) {
70     ownOpts.port = ownOpts.secureEndpoint ? 443 : 80;
71   }
72
73   const opts = Object.assign({}, this.options, ownOpts);
74
75   if (opts.host && opts.path) {
76     // If both a `host` and `path` are specified then it's most likely the
77     // result of a `url.parse()` call... we need to remove the `path` portion so
78     // that `net.connect()` doesn't attempt to open that as a unix socket file.
79     delete opts.path;
80   }
81
82   delete opts.agent;
83   delete opts.hostname;
84   delete opts._defaultAgent;
85   delete opts.defaultPort;
86   delete opts.createConnection;
87
88   // Hint to use "Connection: close"
89   // XXX: non-documented `http` module API :(
90   req._last = true;
91   req.shouldKeepAlive = false;
92
93   // Create the `stream.Duplex` instance
94   let timeout;
95   let timedOut = false;
96   const timeoutMs = this.timeout;
97   const freeSocket = this.freeSocket;
98
99   function onerror(err) {
100     if (req._hadError) return;
101     req.emit('error', err);
102     // For Safety. Some additional errors might fire later on
103     // and we need to make sure we don't double-fire the error event.
104     req._hadError = true;
105   }
106
107   function ontimeout() {
108     timeout = null;
109     timedOut = true;
110     const err = new Error(
111       'A "socket" was not created for HTTP request before ' + timeoutMs + 'ms'
112     );
113     err.code = 'ETIMEOUT';
114     onerror(err);
115   }
116
117   function callbackError(err) {
118     if (timedOut) return;
119     if (timeout != null) {
120       clearTimeout(timeout);
121       timeout = null;
122     }
123     onerror(err);
124   }
125
126   function onsocket(socket) {
127     if (timedOut) return;
128     if (timeout != null) {
129       clearTimeout(timeout);
130       timeout = null;
131     }
132     if (isAgent(socket)) {
133       // `socket` is actually an http.Agent instance, so relinquish
134       // responsibility for this `req` to the Agent from here on
135       socket.addRequest(req, opts);
136     } else if (socket) {
137       function onfree() {
138         freeSocket(socket, opts);
139       }
140       socket.on('free', onfree);
141       req.onSocket(socket);
142     } else {
143       const err = new Error(
144         'no Duplex stream was returned to agent-base for `' + req.method + ' ' + req.path + '`'
145       );
146       onerror(err);
147     }
148   }
149
150   if (!this._promisifiedCallback && this.callback.length >= 3) {
151     // Legacy callback function - convert to a Promise
152     this.callback = promisify(this.callback, this);
153     this._promisifiedCallback = true;
154   }
155
156   if (timeoutMs > 0) {
157     timeout = setTimeout(ontimeout, timeoutMs);
158   }
159
160   try {
161     Promise.resolve(this.callback(req, opts)).then(onsocket, callbackError);
162   } catch (err) {
163     Promise.reject(err).catch(callbackError);
164   }
165 };
166
167 Agent.prototype.freeSocket = function freeSocket(socket, opts) {
168   // TODO reuse sockets
169   socket.destroy();
170 };