Name: js-handler/node_modules/restify/lib/response.js 
1:
// Copyright 2012 Mark Cavage, Inc.  All rights reserved.
2:
 
3:
var crypto = require('crypto');
4:
var http = require('http');
5:
var sprintf = require('util').format;
6:
 
7:
var assert = require('assert-plus');
8:
var mime = require('mime');
9:
var once = require('once');
10:
 
11:
var errors = require('./errors');
12:
var httpDate = require('./http_date');
13:
 
14:
 
15:
 
16:
///--- Globals
17:
 
18:
var HttpError = errors.HttpError;
19:
var RestError = errors.RestError;
20:
 
21:
var Response = http.ServerResponse;
22:
 
23:
 
24:
 
25:
///--- API
26:
 
27:
Response.prototype.cache = function cache(type, options) {
28:
        if (typeof (type) !== 'string') {
29:
                options = type;
30:
                type = 'public';
31:
        }
32:
 
33:
        if (options && options.maxAge !== undefined) {
34:
                assert.number(options.maxAge, 'options.maxAge');
35:
                type += ', max-age=' + options.maxAge;
36:
        }
37:
 
38:
        return (this.header('Cache-Control', type));
39:
};
40:
 
41:
 
42:
Response.prototype.charSet = function charSet(type) {
43:
        assert.string(type, 'charset');
44:
 
45:
        this._charSet = type;
46:
 
47:
        return (this);
48:
};
49:
 
50:
 
51:
Response.prototype.format = function format(body, cb) {
52:
        var log = this.log;
53:
        var formatter;
54:
        var type = this.contentType || this.getHeader('Content-Type');
55:
        var self = this;
56:
 
57:
        if (type && type.indexOf(';') !== '-1')
58:
                type = type.split(';')[0];
59:
 
60:
        if (!(formatter = this.formatters[type])) {
61:
                if (!type) {
62:
                        for (var i = 0; i < this.acceptable.length; i++) {
63:
                                if (this.req.accepts(this.acceptable[i])) {
64:
                                        type = this.acceptable[i];
65:
                                        break;
66:
                                }
67:
                        }
68:
                } else {
69:
                        if (type.indexOf('/') === -1)
70:
                                type = mime.lookup(type);
71:
 
72:
                        if (this.acceptable.indexOf(type) === -1)
73:
                                type = 'application/octet-stream';
74:
                }
75:
 
76:
                formatter = this.formatters[type] || this.formatters['*/*'];
77:
                if (!formatter) {
78:
                        log.warn({
79:
                                req: self.req
80:
                        }, 'no formatter found. Returning 500.');
81:
                        this.statusCode = 500;
82:
                        return (null);
83:
                }
84:
                this.setHeader('Content-Type', type);
85:
        }
86:
 
87:
        if (this._charSet) {
88:
                type = type + '; charset=' + this._charSet;
89:
                this.setHeader('Content-Type', type);
90:
        }
91:
 
92:
        if (body instanceof Error && body.statusCode !== undefined)
93:
                this.statusCode = body.statusCode;
94:
        return (formatter.call(this, this.req, this, body, cb));
95:
};
96:
 
97:
 
98:
Response.prototype.get = function get(name) {
99:
        assert.string(name, 'name');
100:
 
101:
        return (this.getHeader(name));
102:
};
103:
 
104:
 
105:
Response.prototype.getHeaders = function getHeaders() {
106:
        return (this._headers || {});
107:
};
108:
Response.prototype.headers = Response.prototype.getHeaders;
109:
 
110:
 
111:
Response.prototype.header = function header(name, value) {
112:
        assert.string(name, 'name');
113:
 
114:
        if (value === undefined)
115:
                return (this.getHeader(name));
116:
 
117:
        if (value instanceof Date) {
118:
                value = httpDate(value);
119:
        } else if (arguments.length > 2) {
120:
                // Support res.header('foo', 'bar %s', 'baz');
121:
                var arg = Array.prototype.slice.call(arguments).slice(2);
122:
                value = sprintf(value, arg);
123:
        }
124:
 
125:
        this.setHeader(name, value);
126:
        return (value);
127:
};
128:
 
129:
 
130:
Response.prototype.json = function json(code, object, headers) {
131:
        if (!/application\/json/.test(this.header('content-type')))
132:
                this.header('Content-Type', 'application/json');
133:
 
134:
        return (this.send(code, object, headers));
135:
};
136:
 
137:
 
138:
Response.prototype.link = function link(l, rel) {
139:
        assert.string(l, 'link');
140:
        assert.string(rel, 'rel');
141:
 
142:
        var _link = sprintf('<%s>; rel="%s"', l, rel);
143:
        return (this.header('Link', _link));
144:
};
145:
 
146:
 
147:
Response.prototype.send = function send(code, body, headers) {
148:
        var isHead = (this.req.method === 'HEAD');
149:
        var log = this.log;
150:
        var self = this;
151:
 
152:
        if (code === undefined) {
153:
                this.statusCode = 200;
154:
        } else if (code.constructor.name === 'Number') {
155:
                this.statusCode = code;
156:
        } else {
157:
                headers = body;
158:
                body = code;
159:
                code = null;
160:
        }
161:
 
162:
        headers = headers || {};
163:
 
164:
        if (log.trace()) {
165:
                var _props = {
166:
                        code: self.statusCode,
167:
                        headers: headers
168:
                };
169:
                if (body instanceof Error) {
170:
                        _props.err = body;
171:
                } else {
172:
                        _props.body = body;
173:
                }
174:
                log.trace(_props, 'response::send entered');
175:
        }
176:
 
177:
        this._body = body;
178:
 
179:
        function _cb(err, _body) {
180:
                self._data = _body;
181:
                Object.keys(headers).forEach(function (k) {
182:
                        self.setHeader(k, headers[k]);
183:
                });
184:
 
185:
                self.writeHead(self.statusCode);
186:
 
187:
                if (self._data && !(isHead || code === 204 || code === 304))
188:
                        self.write(self._data);
189:
 
190:
                self.end();
191:
 
192:
                if (log.trace())
193:
                        log.trace({res: self}, 'response sent');
194:
        }
195:
 
196:
        if (body) {
197:
                var ret = this.format(body, _cb);
198:
                if (!(ret instanceof Response)) {
199:
                        _cb(null, ret);
200:
                }
201:
        } else {
202:
                _cb(null, null);
203:
        }
204:
 
205:
        return (this);
206:
};
207:
 
208:
 
209:
Response.prototype.set = function set(name, val) {
210:
        var self = this;
211:
 
212:
        if (arguments.length === 2) {
213:
                assert.string(name, 'name');
214:
                this.header(name, val);
215:
        } else {
216:
                assert.object(name, 'object');
217:
                Object.keys(name).forEach(function (k) {
218:
                        self.header(k, name[k]);
219:
                });
220:
        }
221:
 
222:
        return (this);
223:
};
224:
 
225:
 
226:
Response.prototype.status = function status(code) {
227:
        assert.number(code, 'code');
228:
 
229:
        this.statusCode = code;
230:
        return (code);
231:
};
232:
 
233:
 
234:
Response.prototype.toString = function toString() {
235:
        var headers = this.getHeaders();
236:
        var headerString = '';
237:
        var str;
238:
 
239:
        Object.keys(headers).forEach(function (k) {
240:
                headerString += k + ': ' + headers[k] + '\n';
241:
        });
242:
        str = sprintf('HTTP/1.1 %s %s\n%s',
243:
                      this.statusCode,
244:
                      http.STATUS_CODES[this.statusCode],
245:
                      headerString);
246:
 
247:
        return (str);
248:
};
249:
 
250:
if (!Response.prototype.hasOwnProperty('_writeHead'))
251:
        Response.prototype._writeHead = Response.prototype.writeHead;
252:
 
253:
 
254:
Response.prototype.writeHead = function restifyWriteHead() {
255:
        this.emit('header');
256:
 
257:
        if (this.statusCode === 204 || this.statusCode === 304) {
258:
                this.removeHeader('Content-Length');
259:
                this.removeHeader('Content-MD5');
260:
                this.removeHeader('Content-Type');
261:
        }
262:
 
263:
        this._writeHead.apply(this, arguments);
264:
};