Files
node/lib/_http_incoming.js
isaacs 3e1b1dd4a9 Remove excessive copyright/license boilerplate
The copyright and license notice is already in the LICENSE file.  There
is no justifiable reason to also require that it be included in every
file, since the individual files are not individually distributed except
as part of the entire package.
2015-01-12 15:30:28 -08:00

178 lines
4.4 KiB
JavaScript

'use strict';
var util = require('util');
var Stream = require('stream');
function readStart(socket) {
if (socket && !socket._paused && socket.readable)
socket.resume();
}
exports.readStart = readStart;
function readStop(socket) {
if (socket)
socket.pause();
}
exports.readStop = readStop;
/* Abstract base class for ServerRequest and ClientResponse. */
function IncomingMessage(socket) {
Stream.Readable.call(this);
// XXX This implementation is kind of all over the place
// When the parser emits body chunks, they go in this list.
// _read() pulls them out, and when it finds EOF, it ends.
this.socket = socket;
this.connection = socket;
this.httpVersionMajor = null;
this.httpVersionMinor = null;
this.httpVersion = null;
this.complete = false;
this.headers = {};
this.rawHeaders = [];
this.trailers = {};
this.rawTrailers = [];
this.readable = true;
this._pendings = [];
this._pendingIndex = 0;
this.upgrade = null;
// request (server) only
this.url = '';
this.method = null;
// response (client) only
this.statusCode = null;
this.statusMessage = null;
this.client = this.socket;
// flag for backwards compatibility grossness.
this._consuming = false;
// flag for when we decide that this message cannot possibly be
// read by the user, so there's no point continuing to handle it.
this._dumped = false;
}
util.inherits(IncomingMessage, Stream.Readable);
exports.IncomingMessage = IncomingMessage;
IncomingMessage.prototype.setTimeout = function(msecs, callback) {
if (callback)
this.on('timeout', callback);
this.socket.setTimeout(msecs);
};
IncomingMessage.prototype.read = function(n) {
this._consuming = true;
this.read = Stream.Readable.prototype.read;
return this.read(n);
};
IncomingMessage.prototype._read = function(n) {
// We actually do almost nothing here, because the parserOnBody
// function fills up our internal buffer directly. However, we
// do need to unpause the underlying socket so that it flows.
if (this.socket.readable)
readStart(this.socket);
};
// It's possible that the socket will be destroyed, and removed from
// any messages, before ever calling this. In that case, just skip
// it, since something else is destroying this connection anyway.
IncomingMessage.prototype.destroy = function(error) {
if (this.socket)
this.socket.destroy(error);
};
IncomingMessage.prototype._addHeaderLines = function(headers, n) {
if (headers && headers.length) {
var raw, dest;
if (this.complete) {
raw = this.rawTrailers;
dest = this.trailers;
} else {
raw = this.rawHeaders;
dest = this.headers;
}
for (var i = 0; i < n; i += 2) {
var k = headers[i];
var v = headers[i + 1];
raw.push(k);
raw.push(v);
this._addHeaderLine(k, v, dest);
}
}
};
// Add the given (field, value) pair to the message
//
// Per RFC2616, section 4.2 it is acceptable to join multiple instances of the
// same header with a ', ' if the header in question supports specification of
// multiple values this way. If not, we declare the first instance the winner
// and drop the second. Extended header fields (those beginning with 'x-') are
// always joined.
IncomingMessage.prototype._addHeaderLine = function(field, value, dest) {
field = field.toLowerCase();
switch (field) {
// Array headers:
case 'set-cookie':
if (!util.isUndefined(dest[field])) {
dest[field].push(value);
} else {
dest[field] = [value];
}
break;
// list is taken from:
// https://mxr.mozilla.org/mozilla/source/netwerk/protocol/http/src/nsHttpHeaderArray.cpp
case 'content-type':
case 'content-length':
case 'user-agent':
case 'referer':
case 'host':
case 'authorization':
case 'proxy-authorization':
case 'if-modified-since':
case 'if-unmodified-since':
case 'from':
case 'location':
case 'max-forwards':
// drop duplicates
if (util.isUndefined(dest[field]))
dest[field] = value;
break;
default:
// make comma-separated list
if (!util.isUndefined(dest[field]))
dest[field] += ', ' + value;
else {
dest[field] = value;
}
}
};
// Call this instead of resume() if we want to just
// dump all the data to /dev/null
IncomingMessage.prototype._dump = function() {
if (!this._dumped) {
this._dumped = true;
this.resume();
}
};