1 /* Copyright 2015-present Samsung Electronics Co., Ltd. and other contributors
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 var util = require('util');
18 var stream = require('stream');
21 function OutgoingMessage() {
22 stream.Stream.call(this);
28 this.finished = false;
29 this._sentHeader = false;
32 this.connection = null;
33 // response header string : same 'content' as this._headers
35 // response header obj : (key, value) pairs
40 util.inherits(OutgoingMessage, stream.Stream);
42 exports.OutgoingMessage = OutgoingMessage;
45 OutgoingMessage.prototype.end = function(data, encoding, callback) {
48 if (util.isFunction(data)) {
51 } else if (util.isFunction(encoding)) {
62 this._implicitHeader();
66 this.write(data, encoding);
69 // Register finish event handler.
70 if (util.isFunction(callback)) {
71 this.once('finish', callback);
74 // Force flush buffered data.
75 // After all data was sent, emit 'finish' event meaning segment of header and
76 // body were all sent finished. This means different from 'finish' event
77 // emitted by net which indicate there will be no more data to be sent through
78 // the connection. On the other hand emitting 'finish' event from http does
79 // not neccessarily imply end of data transmission since there might be
80 // another segment of data when connection is 'Keep-Alive'.
81 this._send('', function() {
94 OutgoingMessage.prototype._finish = function() {
95 this.emit('prefinish');
99 // This sends chunk directly into socket
100 // TODO: buffering of chunk in the case of socket is not available
101 OutgoingMessage.prototype._send = function(chunk, encoding, callback) {
102 if (util.isFunction(encoding)) {
106 if (util.isBuffer(chunk)) {
107 chunk = chunk.toString();
110 if (!this._sentHeader) {
111 chunk = this._header + "\r\n" + chunk;
112 this._sentHeader = true;
115 return this.connection.write(chunk, encoding, callback);
119 OutgoingMessage.prototype.write = function(chunk, encoding, callback) {
121 this._implicitHeader();
124 if (!this._hasBody) {
128 var ret = this._send(chunk, encoding, callback);
135 // Stringfy header fields of _headers into _header
136 OutgoingMessage.prototype._storeHeader = function(statusLine) {
141 keys = Object.keys(this._headers);
142 for (var i=0; i<keys.length; i++) {
144 headerStr += key + ": " + this._headers[key] + '\r\n';
148 this._header = statusLine + headerStr;
153 OutgoingMessage.prototype.setHeader = function(name, value) {
155 if (this._headers === null) {
159 this._headers[name] = value;
164 OutgoingMessage.prototype.removeHeader = function(name) {
165 if (this._headers === null) {
169 delete this._headers[name];
173 OutgoingMessage.prototype.getHeader = function(name) {
174 return this._headers[name];
178 OutgoingMessage.prototype.setTimeout = function(ms, cb) {
180 this.once('timeout', cb);
183 this.once('socket', function(socket) {
184 socket.setTimeout(msecs);
187 this.socket.setTimeout(msecs);