mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
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.
178 lines
4.4 KiB
JavaScript
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();
|
|
}
|
|
};
|