doc: improvements to debugger.markdown copy
[platform/upstream/nodejs.git] / lib / _http_server.js
1 'use strict';
2
3 const util = require('util');
4 const net = require('net');
5 const EventEmitter = require('events');
6 const HTTPParser = process.binding('http_parser').HTTPParser;
7 const assert = require('assert').ok;
8 const common = require('_http_common');
9 const parsers = common.parsers;
10 const freeParser = common.freeParser;
11 const debug = common.debug;
12 const CRLF = common.CRLF;
13 const continueExpression = common.continueExpression;
14 const chunkExpression = common.chunkExpression;
15 const httpSocketSetup = common.httpSocketSetup;
16 const OutgoingMessage = require('_http_outgoing').OutgoingMessage;
17
18 const STATUS_CODES = exports.STATUS_CODES = {
19   100 : 'Continue',
20   101 : 'Switching Protocols',
21   102 : 'Processing',                 // RFC 2518, obsoleted by RFC 4918
22   200 : 'OK',
23   201 : 'Created',
24   202 : 'Accepted',
25   203 : 'Non-Authoritative Information',
26   204 : 'No Content',
27   205 : 'Reset Content',
28   206 : 'Partial Content',
29   207 : 'Multi-Status',               // RFC 4918
30   208 : 'Already Reported',
31   226 : 'IM Used',
32   300 : 'Multiple Choices',
33   301 : 'Moved Permanently',
34   302 : 'Found',
35   303 : 'See Other',
36   304 : 'Not Modified',
37   305 : 'Use Proxy',
38   307 : 'Temporary Redirect',
39   308 : 'Permanent Redirect',         // RFC 7238
40   400 : 'Bad Request',
41   401 : 'Unauthorized',
42   402 : 'Payment Required',
43   403 : 'Forbidden',
44   404 : 'Not Found',
45   405 : 'Method Not Allowed',
46   406 : 'Not Acceptable',
47   407 : 'Proxy Authentication Required',
48   408 : 'Request Timeout',
49   409 : 'Conflict',
50   410 : 'Gone',
51   411 : 'Length Required',
52   412 : 'Precondition Failed',
53   413 : 'Payload Too Large',
54   414 : 'URI Too Long',
55   415 : 'Unsupported Media Type',
56   416 : 'Range Not Satisfiable',
57   417 : 'Expectation Failed',
58   418 : 'I\'m a teapot',              // RFC 2324
59   421 : 'Misdirected Request',
60   422 : 'Unprocessable Entity',       // RFC 4918
61   423 : 'Locked',                     // RFC 4918
62   424 : 'Failed Dependency',          // RFC 4918
63   425 : 'Unordered Collection',       // RFC 4918
64   426 : 'Upgrade Required',           // RFC 2817
65   428 : 'Precondition Required',      // RFC 6585
66   429 : 'Too Many Requests',          // RFC 6585
67   431 : 'Request Header Fields Too Large',// RFC 6585
68   500 : 'Internal Server Error',
69   501 : 'Not Implemented',
70   502 : 'Bad Gateway',
71   503 : 'Service Unavailable',
72   504 : 'Gateway Timeout',
73   505 : 'HTTP Version Not Supported',
74   506 : 'Variant Also Negotiates',    // RFC 2295
75   507 : 'Insufficient Storage',       // RFC 4918
76   508 : 'Loop Detected',
77   509 : 'Bandwidth Limit Exceeded',
78   510 : 'Not Extended',               // RFC 2774
79   511 : 'Network Authentication Required' // RFC 6585
80 };
81
82 const kOnExecute = HTTPParser.kOnExecute | 0;
83
84
85 function ServerResponse(req) {
86   OutgoingMessage.call(this);
87
88   if (req.method === 'HEAD') this._hasBody = false;
89
90   this.sendDate = true;
91
92   if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
93     this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te);
94     this.shouldKeepAlive = false;
95   }
96 }
97 util.inherits(ServerResponse, OutgoingMessage);
98
99 ServerResponse.prototype._finish = function() {
100   DTRACE_HTTP_SERVER_RESPONSE(this.connection);
101   LTTNG_HTTP_SERVER_RESPONSE(this.connection);
102   COUNTER_HTTP_SERVER_RESPONSE();
103   OutgoingMessage.prototype._finish.call(this);
104 };
105
106
107 exports.ServerResponse = ServerResponse;
108
109 ServerResponse.prototype.statusCode = 200;
110 ServerResponse.prototype.statusMessage = undefined;
111
112 function onServerResponseClose() {
113   // EventEmitter.emit makes a copy of the 'close' listeners array before
114   // calling the listeners. detachSocket() unregisters onServerResponseClose
115   // but if detachSocket() is called, directly or indirectly, by a 'close'
116   // listener, onServerResponseClose is still in that copy of the listeners
117   // array. That is, in the example below, b still gets called even though
118   // it's been removed by a:
119   //
120   //   var EventEmitter = require('events');
121   //   var obj = new EventEmitter();
122   //   obj.on('event', a);
123   //   obj.on('event', b);
124   //   function a() { obj.removeListener('event', b) }
125   //   function b() { throw "BAM!" }
126   //   obj.emit('event');  // throws
127   //
128   // Ergo, we need to deal with stale 'close' events and handle the case
129   // where the ServerResponse object has already been deconstructed.
130   // Fortunately, that requires only a single if check. :-)
131   if (this._httpMessage) this._httpMessage.emit('close');
132 }
133
134 ServerResponse.prototype.assignSocket = function(socket) {
135   assert(!socket._httpMessage);
136   socket._httpMessage = this;
137   socket.on('close', onServerResponseClose);
138   this.socket = socket;
139   this.connection = socket;
140   this.emit('socket', socket);
141   this._flush();
142 };
143
144 ServerResponse.prototype.detachSocket = function(socket) {
145   assert(socket._httpMessage === this);
146   socket.removeListener('close', onServerResponseClose);
147   socket._httpMessage = null;
148   this.socket = this.connection = null;
149 };
150
151 ServerResponse.prototype.writeContinue = function(cb) {
152   this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii', cb);
153   this._sent100 = true;
154 };
155
156 ServerResponse.prototype._implicitHeader = function() {
157   this.writeHead(this.statusCode);
158 };
159
160 ServerResponse.prototype.writeHead = function(statusCode, reason, obj) {
161   var headers;
162
163   if (typeof reason === 'string') {
164     // writeHead(statusCode, reasonPhrase[, headers])
165     this.statusMessage = reason;
166   } else {
167     // writeHead(statusCode[, headers])
168     this.statusMessage =
169         this.statusMessage || STATUS_CODES[statusCode] || 'unknown';
170     obj = reason;
171   }
172   this.statusCode = statusCode;
173
174   if (this._headers) {
175     // Slow-case: when progressive API and header fields are passed.
176     if (obj) {
177       var keys = Object.keys(obj);
178       for (var i = 0; i < keys.length; i++) {
179         var k = keys[i];
180         if (k) this.setHeader(k, obj[k]);
181       }
182     }
183     // only progressive api is used
184     headers = this._renderHeaders();
185   } else {
186     // only writeHead() called
187     headers = obj;
188   }
189
190   var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' +
191                    this.statusMessage + CRLF;
192
193   if (statusCode === 204 || statusCode === 304 ||
194       (100 <= statusCode && statusCode <= 199)) {
195     // RFC 2616, 10.2.5:
196     // The 204 response MUST NOT include a message-body, and thus is always
197     // terminated by the first empty line after the header fields.
198     // RFC 2616, 10.3.5:
199     // The 304 response MUST NOT contain a message-body, and thus is always
200     // terminated by the first empty line after the header fields.
201     // RFC 2616, 10.1 Informational 1xx:
202     // This class of status code indicates a provisional response,
203     // consisting only of the Status-Line and optional headers, and is
204     // terminated by an empty line.
205     this._hasBody = false;
206   }
207
208   // don't keep alive connections where the client expects 100 Continue
209   // but we sent a final status; they may put extra bytes on the wire.
210   if (this._expect_continue && !this._sent100) {
211     this.shouldKeepAlive = false;
212   }
213
214   this._storeHeader(statusLine, headers);
215 };
216
217 ServerResponse.prototype.writeHeader = function() {
218   this.writeHead.apply(this, arguments);
219 };
220
221
222 function Server(requestListener) {
223   if (!(this instanceof Server)) return new Server(requestListener);
224   net.Server.call(this, { allowHalfOpen: true });
225
226   if (requestListener) {
227     this.addListener('request', requestListener);
228   }
229
230   /* eslint-disable max-len */
231   // Similar option to this. Too lazy to write my own docs.
232   // http://www.squid-cache.org/Doc/config/half_closed_clients/
233   // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
234   /* eslint-enable max-len */
235   this.httpAllowHalfOpen = false;
236
237   this.addListener('connection', connectionListener);
238
239   this.addListener('clientError', function(err, conn) {
240     conn.destroy(err);
241   });
242
243   this.timeout = 2 * 60 * 1000;
244
245   this._pendingResponseData = 0;
246 }
247 util.inherits(Server, net.Server);
248
249
250 Server.prototype.setTimeout = function(msecs, callback) {
251   this.timeout = msecs;
252   if (callback)
253     this.on('timeout', callback);
254   return this;
255 };
256
257
258 exports.Server = Server;
259
260
261 function connectionListener(socket) {
262   var self = this;
263   var outgoing = [];
264   var incoming = [];
265   var outgoingData = 0;
266
267   function updateOutgoingData(delta) {
268     // `outgoingData` is an approximate amount of bytes queued through all
269     // inactive responses. If more data than the high watermark is queued - we
270     // need to pause TCP socket/HTTP parser, and wait until the data will be
271     // sent to the client.
272     outgoingData += delta;
273     if (socket._paused && outgoingData < socket._writableState.highWaterMark)
274       return socketOnDrain();
275   }
276
277   function abortIncoming() {
278     while (incoming.length) {
279       var req = incoming.shift();
280       req.emit('aborted');
281       req.emit('close');
282     }
283     // abort socket._httpMessage ?
284   }
285
286   function serverSocketCloseListener() {
287     debug('server socket close');
288     // mark this parser as reusable
289     if (this.parser) {
290       freeParser(this.parser, null, this);
291     }
292
293     abortIncoming();
294   }
295
296   debug('SERVER new http connection');
297
298   httpSocketSetup(socket);
299
300   // If the user has added a listener to the server,
301   // request, or response, then it's their responsibility.
302   // otherwise, destroy on timeout by default
303   if (self.timeout)
304     socket.setTimeout(self.timeout);
305   socket.on('timeout', function() {
306     var req = socket.parser && socket.parser.incoming;
307     var reqTimeout = req && !req.complete && req.emit('timeout', socket);
308     var res = socket._httpMessage;
309     var resTimeout = res && res.emit('timeout', socket);
310     var serverTimeout = self.emit('timeout', socket);
311
312     if (!reqTimeout && !resTimeout && !serverTimeout)
313       socket.destroy();
314   });
315
316   var parser = parsers.alloc();
317   parser.reinitialize(HTTPParser.REQUEST);
318   parser.socket = socket;
319   socket.parser = parser;
320   parser.incoming = null;
321
322   // Propagate headers limit from server instance to parser
323   if (typeof this.maxHeadersCount === 'number') {
324     parser.maxHeaderPairs = this.maxHeadersCount << 1;
325   } else {
326     // Set default value because parser may be reused from FreeList
327     parser.maxHeaderPairs = 2000;
328   }
329
330   socket.addListener('error', socketOnError);
331   socket.addListener('close', serverSocketCloseListener);
332   parser.onIncoming = parserOnIncoming;
333   socket.on('end', socketOnEnd);
334   socket.on('data', socketOnData);
335
336   // We are consuming socket, so it won't get any actual data
337   socket.on('resume', onSocketResume);
338   socket.on('pause', onSocketPause);
339
340   socket.on('drain', socketOnDrain);
341
342   // Override on to unconsume on `data`, `readable` listeners
343   socket.on = socketOnWrap;
344
345   var external = socket._handle._externalStream;
346   if (external) {
347     parser._consumed = true;
348     parser.consume(external);
349   }
350   external = null;
351   parser[kOnExecute] = onParserExecute;
352
353   // TODO(isaacs): Move all these functions out of here
354   function socketOnError(e) {
355     self.emit('clientError', e, this);
356   }
357
358   function socketOnData(d) {
359     assert(!socket._paused);
360     debug('SERVER socketOnData %d', d.length);
361     var ret = parser.execute(d);
362
363     onParserExecuteCommon(ret, d);
364   }
365
366   function onParserExecute(ret, d) {
367     debug('SERVER socketOnParserExecute %d', ret);
368     onParserExecuteCommon(ret, undefined);
369   }
370
371   function onParserExecuteCommon(ret, d) {
372     if (ret instanceof Error) {
373       debug('parse error');
374       socket.destroy(ret);
375     } else if (parser.incoming && parser.incoming.upgrade) {
376       // Upgrade or CONNECT
377       var bytesParsed = ret;
378       var req = parser.incoming;
379       debug('SERVER upgrade or connect', req.method);
380
381       if (!d)
382         d = parser.getCurrentBuffer();
383
384       socket.removeListener('data', socketOnData);
385       socket.removeListener('end', socketOnEnd);
386       socket.removeListener('close', serverSocketCloseListener);
387       unconsume(parser, socket);
388       parser.finish();
389       freeParser(parser, req, null);
390       parser = null;
391
392       var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
393       if (EventEmitter.listenerCount(self, eventName) > 0) {
394         debug('SERVER have listener for %s', eventName);
395         var bodyHead = d.slice(bytesParsed, d.length);
396
397         // TODO(isaacs): Need a way to reset a stream to fresh state
398         // IE, not flowing, and not explicitly paused.
399         socket._readableState.flowing = null;
400         self.emit(eventName, req, socket, bodyHead);
401       } else {
402         // Got upgrade header or CONNECT method, but have no handler.
403         socket.destroy();
404       }
405     }
406
407     if (socket._paused && socket.parser) {
408       // onIncoming paused the socket, we should pause the parser as well
409       debug('pause parser');
410       socket.parser.pause();
411     }
412   }
413
414   function socketOnEnd() {
415     var socket = this;
416     var ret = parser.finish();
417
418     if (ret instanceof Error) {
419       debug('parse error');
420       socket.destroy(ret);
421       return;
422     }
423
424     if (!self.httpAllowHalfOpen) {
425       abortIncoming();
426       if (socket.writable) socket.end();
427     } else if (outgoing.length) {
428       outgoing[outgoing.length - 1]._last = true;
429     } else if (socket._httpMessage) {
430       socket._httpMessage._last = true;
431     } else {
432       if (socket.writable) socket.end();
433     }
434   }
435
436
437   // The following callback is issued after the headers have been read on a
438   // new message. In this callback we setup the response object and pass it
439   // to the user.
440
441   socket._paused = false;
442   function socketOnDrain() {
443     var needPause = outgoingData > socket._writableState.highWaterMark;
444
445     // If we previously paused, then start reading again.
446     if (socket._paused && !needPause) {
447       socket._paused = false;
448       if (socket.parser)
449         socket.parser.resume();
450       socket.resume();
451     }
452   }
453
454   function parserOnIncoming(req, shouldKeepAlive) {
455     incoming.push(req);
456
457     // If the writable end isn't consuming, then stop reading
458     // so that we don't become overwhelmed by a flood of
459     // pipelined requests that may never be resolved.
460     if (!socket._paused) {
461       var needPause = socket._writableState.needDrain ||
462           outgoingData >= socket._writableState.highWaterMark;
463       if (needPause) {
464         socket._paused = true;
465         // We also need to pause the parser, but don't do that until after
466         // the call to execute, because we may still be processing the last
467         // chunk.
468         socket.pause();
469       }
470     }
471
472     var res = new ServerResponse(req);
473     res._onPendingData = updateOutgoingData;
474
475     res.shouldKeepAlive = shouldKeepAlive;
476     DTRACE_HTTP_SERVER_REQUEST(req, socket);
477     LTTNG_HTTP_SERVER_REQUEST(req, socket);
478     COUNTER_HTTP_SERVER_REQUEST();
479
480     if (socket._httpMessage) {
481       // There are already pending outgoing res, append.
482       outgoing.push(res);
483     } else {
484       res.assignSocket(socket);
485     }
486
487     // When we're finished writing the response, check if this is the last
488     // respose, if so destroy the socket.
489     res.on('finish', resOnFinish);
490     function resOnFinish() {
491       // Usually the first incoming element should be our request.  it may
492       // be that in the case abortIncoming() was called that the incoming
493       // array will be empty.
494       assert(incoming.length === 0 || incoming[0] === req);
495
496       incoming.shift();
497
498       // if the user never called req.read(), and didn't pipe() or
499       // .resume() or .on('data'), then we call req._dump() so that the
500       // bytes will be pulled off the wire.
501       if (!req._consuming && !req._readableState.resumeScheduled)
502         req._dump();
503
504       res.detachSocket(socket);
505
506       if (res._last) {
507         socket.destroySoon();
508       } else {
509         // start sending the next message
510         var m = outgoing.shift();
511         if (m) {
512           m.assignSocket(socket);
513         }
514       }
515     }
516
517     if (req.headers.expect !== undefined &&
518         (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) &&
519         continueExpression.test(req.headers['expect'])) {
520       res._expect_continue = true;
521       if (EventEmitter.listenerCount(self, 'checkContinue') > 0) {
522         self.emit('checkContinue', req, res);
523       } else {
524         res.writeContinue();
525         self.emit('request', req, res);
526       }
527     } else {
528       self.emit('request', req, res);
529     }
530     return false; // Not a HEAD response. (Not even a response!)
531   }
532 }
533 exports._connectionListener = connectionListener;
534
535 function onSocketResume() {
536   // It may seem that the socket is resumed, but this is an enemy's trick to
537   // deceive us! `resume` is emitted asynchronously, and may be called from
538   // `incoming.readStart()`. Stop the socket again here, just to preserve the
539   // state.
540   //
541   // We don't care about stream semantics for the consumed socket anyway.
542   if (this._paused) {
543     this.pause();
544     return;
545   }
546
547   if (this._handle && !this._handle.reading) {
548     this._handle.reading = true;
549     this._handle.readStart();
550   }
551 }
552
553 function onSocketPause() {
554   if (this._handle && this._handle.reading) {
555     this._handle.reading = false;
556     this._handle.readStop();
557   }
558 }
559
560 function unconsume(parser, socket) {
561   if (socket._handle) {
562     if (parser._consumed)
563       parser.unconsume(socket._handle._externalStream);
564     parser._consumed = false;
565     socket.removeListener('pause', onSocketPause);
566     socket.removeListener('resume', onSocketResume);
567   }
568 }
569
570 function socketOnWrap(ev, fn) {
571   var res = net.Socket.prototype.on.call(this, ev, fn);
572   if (!this.parser) {
573     this.on = net.Socket.prototype.on;
574     return res;
575   }
576
577   if (ev === 'data' || ev === 'readable')
578     unconsume(this.parser, this);
579
580   return res;
581 }