1 // Copyright Joyent, Inc. and other Node contributors.
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
22 var util = require('util');
23 var net = require('net');
24 var EventEmitter = require('events').EventEmitter;
25 var HTTPParser = process.binding('http_parser').HTTPParser;
26 var assert = require('assert').ok;
28 var common = require('_http_common');
29 var parsers = common.parsers;
30 var freeParser = common.freeParser;
31 var debug = common.debug;
32 var CRLF = common.CRLF;
33 var continueExpression = common.continueExpression;
34 var chunkExpression = common.chunkExpression;
35 var httpSocketSetup = common.httpSocketSetup;
37 var OutgoingMessage = require('_http_outgoing').OutgoingMessage;
40 var STATUS_CODES = exports.STATUS_CODES = {
42 101 : 'Switching Protocols',
43 102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
47 203 : 'Non-Authoritative Information',
49 205 : 'Reset Content',
50 206 : 'Partial Content',
51 207 : 'Multi-Status', // RFC 4918
52 300 : 'Multiple Choices',
53 301 : 'Moved Permanently',
54 302 : 'Moved Temporarily',
58 307 : 'Temporary Redirect',
59 308 : 'Permanent Redirect', // RFC 7238
62 402 : 'Payment Required',
65 405 : 'Method Not Allowed',
66 406 : 'Not Acceptable',
67 407 : 'Proxy Authentication Required',
68 408 : 'Request Time-out',
71 411 : 'Length Required',
72 412 : 'Precondition Failed',
73 413 : 'Request Entity Too Large',
74 414 : 'Request-URI Too Large',
75 415 : 'Unsupported Media Type',
76 416 : 'Requested Range Not Satisfiable',
77 417 : 'Expectation Failed',
78 418 : 'I\'m a teapot', // RFC 2324
79 422 : 'Unprocessable Entity', // RFC 4918
80 423 : 'Locked', // RFC 4918
81 424 : 'Failed Dependency', // RFC 4918
82 425 : 'Unordered Collection', // RFC 4918
83 426 : 'Upgrade Required', // RFC 2817
84 428 : 'Precondition Required', // RFC 6585
85 429 : 'Too Many Requests', // RFC 6585
86 431 : 'Request Header Fields Too Large',// RFC 6585
87 500 : 'Internal Server Error',
88 501 : 'Not Implemented',
90 503 : 'Service Unavailable',
91 504 : 'Gateway Time-out',
92 505 : 'HTTP Version Not Supported',
93 506 : 'Variant Also Negotiates', // RFC 2295
94 507 : 'Insufficient Storage', // RFC 4918
95 509 : 'Bandwidth Limit Exceeded',
96 510 : 'Not Extended', // RFC 2774
97 511 : 'Network Authentication Required' // RFC 6585
101 function ServerResponse(req) {
102 OutgoingMessage.call(this);
104 if (req.method === 'HEAD') this._hasBody = false;
106 this.sendDate = true;
108 if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) {
109 this.useChunkedEncodingByDefault = chunkExpression.test(req.headers.te);
110 this.shouldKeepAlive = false;
113 util.inherits(ServerResponse, OutgoingMessage);
115 ServerResponse.prototype._finish = function() {
116 DTRACE_HTTP_SERVER_RESPONSE(this.connection);
117 COUNTER_HTTP_SERVER_RESPONSE();
118 OutgoingMessage.prototype._finish.call(this);
123 exports.ServerResponse = ServerResponse;
125 ServerResponse.prototype.statusCode = 200;
126 ServerResponse.prototype.statusMessage = undefined;
128 function onServerResponseClose() {
129 // EventEmitter.emit makes a copy of the 'close' listeners array before
130 // calling the listeners. detachSocket() unregisters onServerResponseClose
131 // but if detachSocket() is called, directly or indirectly, by a 'close'
132 // listener, onServerResponseClose is still in that copy of the listeners
133 // array. That is, in the example below, b still gets called even though
134 // it's been removed by a:
136 // var obj = new events.EventEmitter;
137 // obj.on('event', a);
138 // obj.on('event', b);
139 // function a() { obj.removeListener('event', b) }
140 // function b() { throw "BAM!" }
141 // obj.emit('event'); // throws
143 // Ergo, we need to deal with stale 'close' events and handle the case
144 // where the ServerResponse object has already been deconstructed.
145 // Fortunately, that requires only a single if check. :-)
146 if (this._httpMessage) this._httpMessage.emit('close');
149 ServerResponse.prototype.assignSocket = function(socket) {
150 assert(!socket._httpMessage);
151 socket._httpMessage = this;
152 socket.on('close', onServerResponseClose);
153 this.socket = socket;
154 this.connection = socket;
155 this.emit('socket', socket);
159 ServerResponse.prototype.detachSocket = function(socket) {
160 assert(socket._httpMessage === this);
161 socket.removeListener('close', onServerResponseClose);
162 socket._httpMessage = null;
163 this.socket = this.connection = null;
166 ServerResponse.prototype.writeContinue = function(cb) {
167 this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii', cb);
168 this._sent100 = true;
171 ServerResponse.prototype._implicitHeader = function() {
172 this.writeHead(this.statusCode);
175 ServerResponse.prototype.writeHead = function(statusCode, reason, obj) {
178 if (util.isString(reason)) {
179 // writeHead(statusCode, reasonPhrase[, headers])
180 this.statusMessage = reason;
182 // writeHead(statusCode[, headers])
184 this.statusMessage || STATUS_CODES[statusCode] || 'unknown';
187 this.statusCode = statusCode;
190 // Slow-case: when progressive API and header fields are passed.
192 var keys = Object.keys(obj);
193 for (var i = 0; i < keys.length; i++) {
195 if (k) this.setHeader(k, obj[k]);
198 // only progressive api is used
199 headers = this._renderHeaders();
201 // only writeHead() called
205 var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' +
206 this.statusMessage + CRLF;
208 if (statusCode === 204 || statusCode === 304 ||
209 (100 <= statusCode && statusCode <= 199)) {
211 // The 204 response MUST NOT include a message-body, and thus is always
212 // terminated by the first empty line after the header fields.
214 // The 304 response MUST NOT contain a message-body, and thus is always
215 // terminated by the first empty line after the header fields.
216 // RFC 2616, 10.1 Informational 1xx:
217 // This class of status code indicates a provisional response,
218 // consisting only of the Status-Line and optional headers, and is
219 // terminated by an empty line.
220 this._hasBody = false;
223 // don't keep alive connections where the client expects 100 Continue
224 // but we sent a final status; they may put extra bytes on the wire.
225 if (this._expect_continue && !this._sent100) {
226 this.shouldKeepAlive = false;
229 this._storeHeader(statusLine, headers);
232 ServerResponse.prototype.writeHeader = function() {
233 this.writeHead.apply(this, arguments);
237 function Server(requestListener) {
238 if (!(this instanceof Server)) return new Server(requestListener);
239 net.Server.call(this, { allowHalfOpen: true });
241 if (requestListener) {
242 this.addListener('request', requestListener);
245 // Similar option to this. Too lazy to write my own docs.
246 // http://www.squid-cache.org/Doc/config/half_closed_clients/
247 // http://wiki.squid-cache.org/SquidFaq/InnerWorkings#What_is_a_half-closed_filedescriptor.3F
248 this.httpAllowHalfOpen = false;
250 this.addListener('connection', connectionListener);
252 this.addListener('clientError', function(err, conn) {
256 this.timeout = 2 * 60 * 1000;
258 util.inherits(Server, net.Server);
261 Server.prototype.setTimeout = function(msecs, callback) {
262 this.timeout = msecs;
264 this.on('timeout', callback);
268 exports.Server = Server;
271 function connectionListener(socket) {
276 function abortIncoming() {
277 while (incoming.length) {
278 var req = incoming.shift();
282 // abort socket._httpMessage ?
285 function serverSocketCloseListener() {
286 debug('server socket close');
287 // mark this parser as reusable
289 freeParser(this.parser, null, this);
295 debug('SERVER new http connection');
297 httpSocketSetup(socket);
299 // If the user has added a listener to the server,
300 // request, or response, then it's their responsibility.
301 // otherwise, destroy on timeout by default
303 socket.setTimeout(self.timeout);
304 socket.on('timeout', function() {
305 var req = socket.parser && socket.parser.incoming;
306 var reqTimeout = req && !req.complete && req.emit('timeout', socket);
307 var res = socket._httpMessage;
308 var resTimeout = res && res.emit('timeout', socket);
309 var serverTimeout = self.emit('timeout', socket);
311 if (!reqTimeout && !resTimeout && !serverTimeout)
315 var parser = parsers.alloc();
316 parser.reinitialize(HTTPParser.REQUEST);
317 parser.socket = socket;
318 socket.parser = parser;
319 parser.incoming = null;
321 // Propagate headers limit from server instance to parser
322 if (util.isNumber(this.maxHeadersCount)) {
323 parser.maxHeaderPairs = this.maxHeadersCount << 1;
325 // Set default value because parser may be reused from FreeList
326 parser.maxHeaderPairs = 2000;
329 socket.addListener('error', socketOnError);
330 socket.addListener('close', serverSocketCloseListener);
331 parser.onIncoming = parserOnIncoming;
332 socket.on('end', socketOnEnd);
333 socket.on('data', socketOnData);
335 // TODO(isaacs): Move all these functions out of here
336 function socketOnError(e) {
337 self.emit('clientError', e, this);
340 function socketOnData(d) {
341 assert(!socket._paused);
342 debug('SERVER socketOnData %d', d.length);
343 var ret = parser.execute(d);
344 if (ret instanceof Error) {
345 debug('parse error');
347 } else if (parser.incoming && parser.incoming.upgrade) {
348 // Upgrade or CONNECT
349 var bytesParsed = ret;
350 var req = parser.incoming;
351 debug('SERVER upgrade or connect', req.method);
353 socket.removeListener('data', socketOnData);
354 socket.removeListener('end', socketOnEnd);
355 socket.removeListener('close', serverSocketCloseListener);
357 freeParser(parser, req, null);
360 var eventName = req.method === 'CONNECT' ? 'connect' : 'upgrade';
361 if (EventEmitter.listenerCount(self, eventName) > 0) {
362 debug('SERVER have listener for %s', eventName);
363 var bodyHead = d.slice(bytesParsed, d.length);
365 // TODO(isaacs): Need a way to reset a stream to fresh state
366 // IE, not flowing, and not explicitly paused.
367 socket._readableState.flowing = null;
368 self.emit(eventName, req, socket, bodyHead);
370 // Got upgrade header or CONNECT method, but have no handler.
375 if (socket._paused) {
376 // onIncoming paused the socket, we should pause the parser as well
377 debug('pause parser');
378 socket.parser.pause();
382 function socketOnEnd() {
384 var ret = parser.finish();
386 if (ret instanceof Error) {
387 debug('parse error');
392 if (!self.httpAllowHalfOpen) {
394 if (socket.writable) socket.end();
395 } else if (outgoing.length) {
396 outgoing[outgoing.length - 1]._last = true;
397 } else if (socket._httpMessage) {
398 socket._httpMessage._last = true;
400 if (socket.writable) socket.end();
405 // The following callback is issued after the headers have been read on a
406 // new message. In this callback we setup the response object and pass it
409 socket._paused = false;
410 function socketOnDrain() {
411 // If we previously paused, then start reading again.
412 if (socket._paused) {
413 socket._paused = false;
414 socket.parser.resume();
418 socket.on('drain', socketOnDrain);
420 function parserOnIncoming(req, shouldKeepAlive) {
423 // If the writable end isn't consuming, then stop reading
424 // so that we don't become overwhelmed by a flood of
425 // pipelined requests that may never be resolved.
426 if (!socket._paused) {
427 var needPause = socket._writableState.needDrain;
429 socket._paused = true;
430 // We also need to pause the parser, but don't do that until after
431 // the call to execute, because we may still be processing the last
437 var res = new ServerResponse(req);
439 res.shouldKeepAlive = shouldKeepAlive;
440 DTRACE_HTTP_SERVER_REQUEST(req, socket);
441 COUNTER_HTTP_SERVER_REQUEST();
443 if (socket._httpMessage) {
444 // There are already pending outgoing res, append.
447 res.assignSocket(socket);
450 // When we're finished writing the response, check if this is the last
451 // respose, if so destroy the socket.
452 res.on('prefinish', resOnFinish);
453 function resOnFinish() {
454 // Usually the first incoming element should be our request. it may
455 // be that in the case abortIncoming() was called that the incoming
456 // array will be empty.
457 assert(incoming.length === 0 || incoming[0] === req);
461 // if the user never called req.read(), and didn't pipe() or
462 // .resume() or .on('data'), then we call req._dump() so that the
463 // bytes will be pulled off the wire.
464 if (!req._consuming && !req._readableState.resumeScheduled)
467 res.detachSocket(socket);
470 socket.destroySoon();
472 // start sending the next message
473 var m = outgoing.shift();
475 m.assignSocket(socket);
480 if (!util.isUndefined(req.headers.expect) &&
481 (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) &&
482 continueExpression.test(req.headers['expect'])) {
483 res._expect_continue = true;
484 if (EventEmitter.listenerCount(self, 'checkContinue') > 0) {
485 self.emit('checkContinue', req, res);
488 self.emit('request', req, res);
491 self.emit('request', req, res);
493 return false; // Not a HEAD response. (Not even a response!)
496 exports._connectionListener = connectionListener;