// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
+'use strict';
+
var assert = require('assert').ok;
var Stream = require('stream');
var timers = require('timers');
this.finished = false;
this._hangupClose = false;
+ this._headerSent = false;
this.socket = null;
this.connection = null;
+ this._header = null;
+ this._headers = null;
+ this._headerNames = {};
}
util.inherits(OutgoingMessage, Stream);
}
// Date header
- if (this.sendDate == true && state.sentDateHeader == false) {
+ if (this.sendDate === true && state.sentDateHeader === false) {
state.messageHeader += 'Date: ' + utcDate() + CRLF;
}
// of creating security liabilities, so suppress the zero chunk and force
// the connection to close.
var statusCode = this.statusCode;
- if ((statusCode == 204 || statusCode === 304) &&
+ if ((statusCode === 204 || statusCode === 304) &&
this.chunkedEncoding === true) {
debug(statusCode + ' response should not use chunked encoding,' +
' closing connection.');
}
}
- if (state.sentContentLengthHeader == false &&
- state.sentTransferEncodingHeader == false) {
+ if (state.sentContentLengthHeader === false &&
+ state.sentTransferEncodingHeader === false) {
if (this._hasBody && !this._removedHeader['transfer-encoding']) {
if (this.useChunkedEncodingByDefault) {
state.messageHeader += 'Transfer-Encoding: chunked\r\n';
OutgoingMessage.prototype.setHeader = function(name, value) {
- if (arguments.length < 2) {
- throw new Error('`name` and `value` are required for setHeader().');
- }
-
- if (this._header) {
+ if (typeof name !== 'string')
+ throw new TypeError('"name" should be a string');
+ if (value === undefined)
+ throw new Error('"name" and "value" are required for setHeader().');
+ if (this._header)
throw new Error('Can\'t set headers after they are sent.');
- }
+
+ if (this._headers === null)
+ this._headers = {};
var key = name.toLowerCase();
- this._headers = this._headers || {};
- this._headerNames = this._headerNames || {};
this._headers[key] = value;
this._headerNames[key] = name;
- if (automaticHeaders[key]) {
+ if (automaticHeaders[key])
this._removedHeader[key] = false;
- }
};
var headers = {};
var keys = Object.keys(this._headers);
+
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
headers[this._headerNames[key]] = this._headers[key];
OutgoingMessage.prototype.write = function(chunk, encoding, callback) {
+ var self = this;
+
+ if (this.finished) {
+ var err = new Error('write after end');
+ process.nextTick(function() {
+ self.emit('error', err);
+ if (callback) callback(err);
+ });
+
+ return true;
+ }
+
if (!this._header) {
this._implicitHeader();
}
else
len = chunk.length;
- if (this.connection)
+ if (this.connection && !this.connection.corked) {
this.connection.cork();
+ var conn = this.connection;
+ process.nextTick(function connectionCork() {
+ if (conn)
+ conn.uncork();
+ });
+ }
this._send(len.toString(16), 'binary', null);
this._send(crlf_buf, null, null);
this._send(chunk, encoding, null);
ret = this._send(crlf_buf, null, callback);
- if (this.connection)
- this.connection.uncork();
}
} else {
ret = this._send(chunk, encoding, callback);
ret = this.write(data, encoding);
}
- if (this.chunkedEncoding) {
+ if (this._hasBody && this.chunkedEncoding) {
ret = this._send('0\r\n' + this._trailer + '\r\n', 'binary', finish);
} else {
// Force a flush, HACK.
}
}
};
+
+
+OutgoingMessage.prototype.flush = function() {
+ if (!this._header) {
+ // Force-flush the headers.
+ this._implicitHeader();
+ this._send('');
+ }
+};