arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
socketioMEANseed/www/node_modules/union/lib/response-stream.js
www/node_modules/union/lib/response-stream.jsRaw
  1/*
  2 * response-stream.js: A Stream focused on writing any relevant information to
  3 * a raw http.ServerResponse object.
  4 *
  5 * (C) 2011, Charlie Robbins & the Contributors
  6 * MIT LICENSE
  7 *
  8 */
  9
 10var util = require('util'),
 11    HttpStream = require('./http-stream');
 12
 13var STATUS_CODES = require('http').STATUS_CODES;
 14
 15//
 16// ### function ResponseStream (options)
 17//
 18//
 19var ResponseStream = module.exports = function (options) {
 20  var self = this,
 21      key;
 22
 23  options = options || {};
 24  HttpStream.call(this, options);
 25
 26  this.writeable = true;
 27  this.response = options.response;
 28
 29  if (options.headers) {
 30    for (key in options.headers) {
 31      this.response.setHeader(key, options.headers[key]);
 32    }
 33  }
 34
 35  //
 36  // Proxy `statusCode` changes to the actual `response.statusCode`.
 37  //
 38  Object.defineProperty(this, 'statusCode', {
 39    get: function () {
 40      return self.response.statusCode;
 41    },
 42    set: function (value) {
 43      self.response.statusCode = value;
 44    },
 45    enumerable: true,
 46    configurable: true
 47  });
 48
 49  if (this.response) {
 50    this._headers = this.response._headers = this.response._headers || {};
 51
 52    // Patch to node core
 53    this.response._headerNames = this.response._headerNames || {};
 54
 55    //
 56    // Proxy to emit "header" event
 57    //
 58    this._renderHeaders = this.response._renderHeaders;
 59    this.response._renderHeaders = function () {
 60      if (!self._emittedHeader) {
 61        self._emittedHeader = true;
 62        self.headerSent = true;
 63        self._header = true;
 64        self.emit('header');
 65      }
 66
 67      return self._renderHeaders.call(self.response);
 68    };
 69  }
 70};
 71
 72util.inherits(ResponseStream, HttpStream);
 73
 74ResponseStream.prototype.writeHead = function (statusCode, statusMessage, headers) {
 75  if (typeof statusMessage === 'string') {
 76    this.response.statusMessage = statusMessage;
 77  } else {
 78    this.response.statusMessage = this.response.statusMessage
 79      || STATUS_CODES[statusCode] || 'unknown';
 80    headers = statusMessage;
 81  }
 82
 83  this.response.statusCode = statusCode;
 84
 85  if (headers) {
 86    var keys = Object.keys(headers);
 87    for (var i = 0; i < keys.length; i++) {
 88      var k = keys[i];
 89      if (k) this.response.setHeader(k, headers[k]);
 90    }
 91  }
 92};
 93
 94//
 95// Create pass-thru for the necessary
 96// `http.ServerResponse` methods.
 97//
 98['setHeader', 'getHeader', 'removeHeader', '_implicitHeader', 'addTrailers'].forEach(function (method) {
 99  ResponseStream.prototype[method] = function () {
100    return this.response[method].apply(this.response, arguments);
101  };
102});
103
104ResponseStream.prototype.json = function (obj) {
105  if (!this.response.writable) {
106    return;
107  }
108
109  if (typeof obj === 'number') {
110    this.response.statusCode = obj;
111    obj = arguments[1];
112  }
113
114  this.modified = true;
115
116  if (!this.response._header && this.response.getHeader('content-type') !== 'application/json') {
117    this.response.setHeader('content-type', 'application/json');
118  }
119
120  this.end(obj ? JSON.stringify(obj) : '');
121};
122
123ResponseStream.prototype.html = function (str) {
124  if (!this.response.writable) {
125    return;
126  }
127
128  if (typeof str === 'number') {
129    this.response.statusCode = str;
130    str = arguments[1];
131  }
132
133  this.modified = true;
134
135  if (!this.response._header && this.response.getHeader('content-type') !== 'text/html') {
136    this.response.setHeader('content-type', 'text/html');
137  }
138
139  this.end(str ? str: '');
140};
141
142ResponseStream.prototype.text = function (str) {
143  if (!this.response.writable) {
144    return;
145  }
146
147  if (typeof str === 'number') {
148    this.response.statusCode = str;
149    str = arguments[1];
150  }
151
152  this.modified = true;
153
154  if (!this.response._header && this.response.getHeader('content-type') !== 'text/plain') {
155    this.response.setHeader('content-type', 'text/plain');
156  }
157
158  this.end(str ? str: '');
159};
160
161ResponseStream.prototype.end = function (data) {
162  if (data && this.writable) {
163    this.emit('data', data);
164  }
165
166  this.modified = true;
167  this.emit('end');
168};
169
170ResponseStream.prototype.pipe = function () {
171  var self = this, 
172      dest;
173
174  self.dest = dest = HttpStream.prototype.pipe.apply(self, arguments);
175  
176  dest.on('drain', function() {
177    self.emit('drain')
178  })
179  return dest;
180};
181
182ResponseStream.prototype.write = function (data) {
183  this.modified = true;
184
185  if (this.writable) {
186    return this.dest.write(data);
187  }
188};
189
190ResponseStream.prototype.redirect = function (path, status) {
191  var url = '';
192
193  if (~path.indexOf('://')) {
194    url = path;
195  } else {
196    url += this.req.connection.encrypted ? 'https://' : 'http://';
197    url += this.req.headers.host;
198    url += (path[0] === '/') ? path : '/' + path;
199  }
200
201  this.res.writeHead(status || 302, { 'Location': url });
202  this.end();
203};