doc: improvements to console.markdown copy
[platform/upstream/nodejs.git] / lib / https.js
1 'use strict';
2
3 const tls = require('tls');
4 const url = require('url');
5 const http = require('http');
6 const util = require('util');
7 const inherits = util.inherits;
8 const debug = util.debuglog('https');
9
10 function Server(opts, requestListener) {
11   if (!(this instanceof Server)) return new Server(opts, requestListener);
12
13   if (process.features.tls_npn && !opts.NPNProtocols) {
14     opts.NPNProtocols = ['http/1.1', 'http/1.0'];
15   }
16
17   tls.Server.call(this, opts, http._connectionListener);
18
19   this.httpAllowHalfOpen = false;
20
21   if (requestListener) {
22     this.addListener('request', requestListener);
23   }
24
25   this.addListener('clientError', function(err, conn) {
26     conn.destroy();
27   });
28
29   this.timeout = 2 * 60 * 1000;
30 }
31 inherits(Server, tls.Server);
32 exports.Server = Server;
33
34 Server.prototype.setTimeout = http.Server.prototype.setTimeout;
35
36 exports.createServer = function(opts, requestListener) {
37   return new Server(opts, requestListener);
38 };
39
40
41 // HTTPS agents.
42
43 function createConnection(port, host, options) {
44   if (port !== null && typeof port === 'object') {
45     options = port;
46   } else if (host !== null && typeof host === 'object') {
47     options = host;
48   } else if (options === null || typeof options !== 'object') {
49     options = {};
50   }
51
52   if (typeof port === 'number') {
53     options.port = port;
54   }
55
56   if (typeof host === 'string') {
57     options.host = host;
58   }
59
60   debug('createConnection', options);
61
62   if (options._agentKey) {
63     const session = this._getSession(options._agentKey);
64     if (session) {
65       debug('reuse session for %j', options._agentKey);
66       options = util._extend({
67         session: session
68       }, options);
69     }
70   }
71
72   const self = this;
73   const socket = tls.connect(options, function() {
74     if (!options._agentKey)
75       return;
76
77     self._cacheSession(options._agentKey, socket.getSession());
78   });
79   return socket;
80 }
81
82
83 function Agent(options) {
84   http.Agent.call(this, options);
85   this.defaultPort = 443;
86   this.protocol = 'https:';
87   this.maxCachedSessions = this.options.maxCachedSessions;
88   if (this.maxCachedSessions === undefined)
89     this.maxCachedSessions = 100;
90
91   this._sessionCache = {
92     map: {},
93     list: []
94   };
95 }
96 inherits(Agent, http.Agent);
97 Agent.prototype.createConnection = createConnection;
98
99 Agent.prototype.getName = function(options) {
100   var name = http.Agent.prototype.getName.call(this, options);
101
102   name += ':';
103   if (options.ca)
104     name += options.ca;
105
106   name += ':';
107   if (options.cert)
108     name += options.cert;
109
110   name += ':';
111   if (options.ciphers)
112     name += options.ciphers;
113
114   name += ':';
115   if (options.key)
116     name += options.key;
117
118   name += ':';
119   if (options.pfx)
120     name += options.pfx;
121
122   name += ':';
123   if (options.rejectUnauthorized !== undefined)
124     name += options.rejectUnauthorized;
125
126   return name;
127 };
128
129 Agent.prototype._getSession = function _getSession(key) {
130   return this._sessionCache.map[key];
131 };
132
133 Agent.prototype._cacheSession = function _cacheSession(key, session) {
134   // Fast case - update existing entry
135   if (this._sessionCache.map[key]) {
136     this._sessionCache.map[key] = session;
137     return;
138   }
139
140   // Put new entry
141   if (this._sessionCache.list.length >= this.maxCachedSessions) {
142     const oldKey = this._sessionCache.list.shift();
143     debug('evicting %j', oldKey);
144     delete this._sessionCache.map[oldKey];
145   }
146
147   this._sessionCache.list.push(key);
148   this._sessionCache.map[key] = session;
149 };
150
151 const globalAgent = new Agent();
152
153 exports.globalAgent = globalAgent;
154 exports.Agent = Agent;
155
156 exports.request = function(options, cb) {
157   if (typeof options === 'string') {
158     options = url.parse(options);
159   } else {
160     options = util._extend({}, options);
161   }
162   options._defaultAgent = globalAgent;
163   return http.request(options, cb);
164 };
165
166 exports.get = function(options, cb) {
167   var req = exports.request(options, cb);
168   req.end();
169   return req;
170 };