|
|
/* * response-stream.js: A Stream focused on writing any relevant information to * a raw http.ServerResponse object. * * (C) 2011, Charlie Robbins & the Contributors * MIT LICENSE * */
var util = require('util'), HttpStream = require('./http-stream');
var STATUS_CODES = require('http').STATUS_CODES;
//
// ### function ResponseStream (options)
//
//
var ResponseStream = module.exports = function (options) { var self = this, key;
options = options || {}; HttpStream.call(this, options);
this.writeable = true; this.response = options.response;
if (options.headers) { for (key in options.headers) { this.response.setHeader(key, options.headers[key]); } }
//
// Proxy `statusCode` changes to the actual `response.statusCode`.
//
Object.defineProperty(this, 'statusCode', { get: function () { return self.response.statusCode; }, set: function (value) { self.response.statusCode = value; }, enumerable: true, configurable: true });
if (this.response) { this._headers = this.response._headers = this.response._headers || {};
// Patch to node core
this.response._headerNames = this.response._headerNames || {};
//
// Proxy to emit "header" event
//
this._renderHeaders = this.response._renderHeaders; this.response._renderHeaders = function () { if (!self._emittedHeader) { self._emittedHeader = true; self.headerSent = true; self._header = true; self.emit('header'); }
return self._renderHeaders.call(self.response); }; } };
util.inherits(ResponseStream, HttpStream);
ResponseStream.prototype.writeHead = function (statusCode, statusMessage, headers) { if (typeof statusMessage === 'string') { this.response.statusMessage = statusMessage; } else { this.response.statusMessage = this.response.statusMessage || STATUS_CODES[statusCode] || 'unknown'; headers = statusMessage; }
this.response.statusCode = statusCode;
if (headers) { var keys = Object.keys(headers); for (var i = 0; i < keys.length; i++) { var k = keys[i]; if (k) this.response.setHeader(k, headers[k]); } } };
//
// Create pass-thru for the necessary
// `http.ServerResponse` methods.
//
['setHeader', 'getHeader', 'removeHeader', '_implicitHeader', 'addTrailers'].forEach(function (method) { ResponseStream.prototype[method] = function () { return this.response[method].apply(this.response, arguments); }; });
ResponseStream.prototype.json = function (obj) { if (!this.response.writable) { return; }
if (typeof obj === 'number') { this.response.statusCode = obj; obj = arguments[1]; }
this.modified = true;
if (!this.response._header && this.response.getHeader('content-type') !== 'application/json') { this.response.setHeader('content-type', 'application/json'); }
this.end(obj ? JSON.stringify(obj) : ''); };
ResponseStream.prototype.html = function (str) { if (!this.response.writable) { return; }
if (typeof str === 'number') { this.response.statusCode = str; str = arguments[1]; }
this.modified = true;
if (!this.response._header && this.response.getHeader('content-type') !== 'text/html') { this.response.setHeader('content-type', 'text/html'); }
this.end(str ? str: ''); };
ResponseStream.prototype.text = function (str) { if (!this.response.writable) { return; }
if (typeof str === 'number') { this.response.statusCode = str; str = arguments[1]; }
this.modified = true;
if (!this.response._header && this.response.getHeader('content-type') !== 'text/plain') { this.response.setHeader('content-type', 'text/plain'); }
this.end(str ? str: ''); };
ResponseStream.prototype.end = function (data) { if (data && this.writable) { this.emit('data', data); }
this.modified = true; this.emit('end'); };
ResponseStream.prototype.pipe = function () { var self = this, dest;
self.dest = dest = HttpStream.prototype.pipe.apply(self, arguments); dest.on('drain', function() { self.emit('drain') }) return dest; };
ResponseStream.prototype.write = function (data) { this.modified = true;
if (this.writable) { return this.dest.write(data); } };
ResponseStream.prototype.redirect = function (path, status) { var url = '';
if (~path.indexOf('://')) { url = path; } else { url += this.req.connection.encrypted ? 'https://' : 'http://'; url += this.req.headers.host; url += (path[0] === '/') ? path : '/' + path; }
this.res.writeHead(status || 302, { 'Location': url }); this.end(); };
|