Name: js-handler/node_modules/restify/lib/server.js 
1:
// Copyright 2012 Mark Cavage, Inc.  All rights reserved.
2:
 
3:
var domain = require('domain');
4:
var EventEmitter = require('events').EventEmitter;
5:
var http = require('http');
6:
var https = require('https');
7:
var url = require('url');
8:
var util = require('util');
9:
 
10:
var assert = require('assert-plus');
11:
var mime = require('mime');
12:
var once = require('once');
13:
var spdy = require('spdy');
14:
var uuid = require('node-uuid');
15:
 
16:
var dtrace = require('./dtrace');
17:
var errors = require('./errors');
18:
var formatters = require('./formatters');
19:
var shallowCopy = require('./utils').shallowCopy;
20:
var upgrade = require('./upgrade');
21:
 
22:
var semver = require('semver');
23:
var maxSatisfying = semver.maxSatisfying;
24:
 
25:
// Ensure these are loaded
26:
require('./request');
27:
require('./response');
28:
 
29:
 
30:
 
31:
///--- Globals
32:
 
33:
var sprintf = util.format;
34:
 
35:
var BadMethodError = errors.BadMethodError;
36:
var InvalidVersionError = errors.InvalidVersionError;
37:
var ResourceNotFoundError = errors.ResourceNotFoundError;
38:
 
39:
var PROXY_EVENTS = [
40:
        'clientError',
41:
        'close',
42:
        'connection',
43:
        'error',
44:
        'listening',
45:
        'secureConnection'
46:
];
47:
 
48:
 
49:
 
50:
///--- Helpers
51:
 
52:
function argumentsToChain(args, start) {
53:
        assert.ok(args);
54:
 
55:
        args = Array.prototype.slice.call(args, start);
56:
 
57:
        if (args.length < 0)
58:
                throw new TypeError('handler (function) required');
59:
 
60:
        var chain = [];
61:
 
62:
        function process(handlers) {
63:
                for (var i = 0; i < handlers.length; i++) {
64:
                        if (Array.isArray(handlers[i])) {
65:
                                process(handlers[i], 0);
66:
                        } else {
67:
                                assert.func(handlers[i], 'handler');
68:
                                chain.push(handlers[i]);
69:
                        }
70:
                }
71:
 
72:
                return (chain);
73:
        }
74:
 
75:
        return (process(args));
76:
}
77:
 
78:
 
79:
function mergeFormatters(fmt) {
80:
        var arr = [];
81:
        var defaults = Object.keys(formatters).length;
82:
        var i = 0;
83:
        var obj = {};
84:
 
85:
        function addFormatter(src, k) {
86:
                assert.func(src[k], 'formatter');
87:
 
88:
                var q;
89:
                var t = k;
90:
                if (k.indexOf(';') !== -1) {
91:
                        /* JSSTYLED */
92:
                        var tmp = k.split(/\s*;\s*/);
93:
                        t = tmp[0];
94:
                        if (tmp[1].indexOf('q=') !== -1) {
95:
                                q = parseFloat(tmp[1].split('=')[1], 10) * 10;
96:
                        }
97:
                }
98:
 
99:
                if (k.indexOf('/') === -1)
100:
                        k = mime.lookup(k);
101:
 
102:
                obj[t] = src[k];
103:
                arr.push({
104:
                        q: q || (i + defaults),
105:
                        t: t
106:
                });
107:
                i++;
108:
        }
109:
 
110:
        Object.keys(formatters).forEach(addFormatter.bind(this, formatters));
111:
        Object.keys(fmt || {}).forEach(addFormatter.bind(this, fmt || {}));
112:
 
113:
        arr = arr.sort(function (a, b) {
114:
                return (b.q - a.q);
115:
        }).map(function (a) {
116:
                return (a.t);
117:
        });
118:
 
119:
        return ({
120:
                formatters: obj,
121:
                acceptable: arr
122:
        });
123:
}
124:
 
125:
 
126:
function ifError(n) {
127:
        function _ifError(err) {
128:
                if (err) {
129:
                        err._restify_next = n;
130:
                        throw err;
131:
                }
132:
        }
133:
        return (_ifError);
134:
}
135:
 
136:
 
137:
function emitRouteError(server, req, res, err) {
138:
        var name;
139:
        if (err.name === 'ResourceNotFoundError') {
140:
                name = 'NotFound';
141:
        } else if (err.name === 'InvalidVersionError') {
142:
                name = 'VersionNotAllowed';
143:
        } else {
144:
                name = err.name.replace(/Error$/, '');
145:
        }
146:
        if (server.listeners(name).length > 0) {
147:
                server.emit(name, req, res, once(function () {
148:
                        server.emit('after', req, res, null);
149:
                }));
150:
        } else {
151:
                res.send(err);
152:
                server.emit('after', req, res, null);
153:
        }
154:
}
155:
 
156:
 
157:
function optionsError(err, req, res) {
158:
        var code = err.statusCode;
159:
        var ok = false;
160:
 
161:
        if (code === 404 && req.method === 'OPTIONS' && req.url === '*') {
162:
                res.send(200);
163:
                ok = true;
164:
        }
165:
 
166:
        return (ok);
167:
}
168:
 
169:
 
170:
 
171:
///--- API
172:
 
173:
function Server(options) {
174:
        assert.object(options, 'options');
175:
        assert.object(options.log, 'options.log');
176:
        assert.object(options.router, 'options.router');
177:
 
178:
        var self = this;
179:
 
180:
        EventEmitter.call(this);
181:
 
182:
        this.before = [];
183:
        this.chain = [];
184:
        this.log = options.log;
185:
        this.name = options.name || 'restify';
186:
        this.router = options.router;
187:
        this.routes = {};
188:
        this.secure = false;
189:
        this.versions = options.versions || options.version || [];
190:
 
191:
        var fmt = mergeFormatters(options.formatters);
192:
        this.acceptable = fmt.acceptable;
193:
        this.formatters = fmt.formatters;
194:
 
195:
        if (options.spdy) {
196:
                this.spdy = true;
197:
                this.server = spdy.createServer(options.spdy);
198:
        } else if ((options.cert || options.certificate) && options.key) {
199:
                this.ca = options.ca;
200:
                this.certificate = options.certificate || options.cert;
201:
                this.key = options.key;
202:
                this.passphrase = options.passphrase || null;
203:
                this.secure = true;
204:
 
205:
                this.server = https.createServer({
206:
                        ca: self.ca,
207:
                        cert: self.certificate,
208:
                        key: self.key,
209:
                        passphrase: self.passphrase,
210:
                        rejectUnauthorized: options.rejectUnauthorized,
211:
                        requestCert: options.requestCert
212:
                });
213:
        } else {
214:
                this.server = http.createServer();
215:
        }
216:
 
217:
        this.router.on('mount', this.emit.bind(this, 'mount'));
218:
 
219:
        if (!options.handleUpgrades && PROXY_EVENTS.indexOf('upgrade') === -1)
220:
                PROXY_EVENTS.push('upgrade');
221:
        PROXY_EVENTS.forEach(function (e) {
222:
                self.server.on(e, self.emit.bind(self, e));
223:
        });
224:
 
225:
        // Now the things we can't blindly proxy
226:
        this.server.on('checkContinue', function onCheckContinue(req, res) {
227:
                if (self.listeners('checkContinue').length > 0) {
228:
                        self.emit('checkContinue', req, res);
229:
                        return;
230:
                }
231:
 
232:
                if (!options.noWriteContinue)
233:
                        res.writeContinue();
234:
 
235:
                self._setupRequest(req, res);
236:
                self._handle(req, res, true);
237:
        });
238:
 
239:
        if (options.handleUpgrades) {
240:
                this.server.on('upgrade', function onUpgrade(req, socket,
241:
                    head) {
242:
                        req._upgradeRequest = true;
243:
                        var res = upgrade.createResponse(req, socket, head);
244:
                        self._setupRequest(req, res);
245:
                        self._handle(req, res);
246:
                });
247:
        }
248:
 
249:
        this.server.on('request', function onRequest(req, res) {
250:
                /* JSSTYLED */
251:
                if (/^\/socket.io.*/.test(req.url) &&
252:
                    self.listeners('request').length > 0) {
253:
                        self.emit('request', req, res);
254:
                        return;
255:
                }
256:
 
257:
                self._setupRequest(req, res);
258:
                self._handle(req, res);
259:
        });
260:
 
261:
        this.__defineGetter__('maxHeadersCount', function () {
262:
                return (self.server.maxHeadersCount);
263:
        });
264:
 
265:
        this.__defineSetter__('maxHeadersCount', function (c) {
266:
                self.server.maxHeadersCount = c;
267:
                return (c);
268:
        });
269:
 
270:
 
271:
        this.__defineGetter__('url', function () {
272:
                if (self.socketPath)
273:
                        return ('http://' + self.socketPath);
274:
 
275:
                var addr = self.address();
276:
                var str = '';
277:
                if (self.spdy) {
278:
                        str += 'spdy://';
279:
                } else if (self.secure) {
280:
                        str += 'https://';
281:
                } else {
282:
                        str += 'http://';
283:
                }
284:
 
285:
                if (addr) {
286:
                        str += addr.address;
287:
                        str += ':';
288:
                        str += addr.port;
289:
                } else {
290:
                        str += '169.254.0.1:0000';
291:
                }
292:
 
293:
                return (str);
294:
        });
295:
}
296:
util.inherits(Server, EventEmitter);
297:
module.exports = Server;
298:
 
299:
 
300:
Server.prototype.address = function address() {
301:
        return (this.server.address());
302:
};
303:
 
304:
/**
305:
 * Gets the server up and listening.
306:
 *
307:
 * You can call like:
308:
 *  server.listen(80)
309:
 *  server.listen(80, '127.0.0.1')
310:
 *  server.listen('/tmp/server.sock')
311:
 *
312:
 * @param {Function} callback optionally get notified when listening.
313:
 * @throws {TypeError} on bad input.
314:
 */
315:
Server.prototype.listen = function listen() {
316:
        var args = Array.prototype.slice.call(arguments);
317:
        return (this.server.listen.apply(this.server, args));
318:
};
319:
 
320:
 
321:
/**
322:
 * Shuts down this server, and invokes callback (optionally) when done.
323:
 *
324:
 * @param {Function} callback optional callback to invoke when done.
325:
 */
326:
Server.prototype.close = function close(callback) {
327:
        if (callback)
328:
                assert.func(callback, 'callback');
329:
 
330:
        this.server.once('close', function onClose() {
331:
                return (callback ? callback() : false);
332:
        });
333:
 
334:
        return (this.server.close());
335:
};
336:
 
337:
 
338:
// Register all the routing methods
339:
/**
340:
 * Mounts a chain on the given path against this HTTP verb
341:
 *
342:
 * @param {Object} options the URL to handle, at minimum.
343:
 * @return {Route} the newly created route.
344:
 */
345:
[
346:
        'del',
347:
        'get',
348:
        'head',
349:
        'opts',
350:
        'post',
351:
        'put',
352:
        'patch'
353:
].forEach(function (method) {
354:
        Server.prototype[method] = function (opts) {
355:
                if (opts instanceof RegExp || typeof (opts) === 'string') {
356:
                        opts = {
357:
                                path: opts
358:
                        };
359:
                } else if (typeof (opts) === 'object') {
360:
                        opts = shallowCopy(opts);
361:
                } else {
362:
                        throw new TypeError('path (string) required');
363:
                }
364:
 
365:
                if (arguments.length < 2)
366:
                        throw new TypeError('handler (function) required');
367:
 
368:
                var chain = [];
369:
                var route;
370:
                var self = this;
371:
 
372:
                function addHandler(h) {
373:
                        assert.func(h, 'handler');
374:
 
375:
                        chain.push(h);
376:
                }
377:
 
378:
                if (method === 'del')
379:
                        method = 'DELETE';
380:
                if (method === 'opts')
381:
                        method = 'OPTIONS';
382:
                opts.method = method.toUpperCase();
383:
                opts.versions = opts.versions || opts.version || self.versions;
384:
                if (!Array.isArray(opts.versions))
385:
                        opts.versions = [opts.versions];
386:
 
387:
                if (!opts.name) {
388:
                        opts.name = method + '-' + (opts.path || opts.url);
389:
                        if (opts.versions.length > 0) {
390:
                                opts.name += '-' + opts.versions.join('--');
391:
                        }
392:
 
393:
                        opts.name = opts.name.replace(/\W/g, '').toLowerCase();
394:
                        if (this.router.mounts[opts.name]) // GH-401
395:
                                opts.name += uuid.v4().substr(0, 7);
396:
                } else {
397:
                        opts.name = opts.name.replace(/\W/g, '').toLowerCase();
398:
                }
399:
 
400:
 
401:
                if (!(route = this.router.mount(opts)))
402:
                        return (false);
403:
 
404:
                this.chain.forEach(addHandler);
405:
                argumentsToChain(arguments, 1).forEach(addHandler);
406:
                this.routes[route] = chain;
407:
 
408:
                return (route);
409:
        };
410:
});
411:
 
412:
 
413:
/**
414:
 * Minimal port of the functionality offered by Express.js Route Param
415:
 * Pre-conditions
416:
 * @link http://expressjs.com/guide.html#route-param%20pre-conditions
417:
 *
418:
 * This basically piggy-backs on the `server.use` method. It attaches a
419:
 * new middleware function that only fires if the specified parameter exists
420:
 * in req.params
421:
 *
422:
 * Exposes an API:
423:
 *   server.param("user", function (req, res, next) {
424:
 *     // load the user's information here, always making sure to call next()
425:
 *   });
426:
 *
427:
 * @param {String} The name of the URL param to respond to
428:
 * @param {Function} The middleware function to execute
429:
 */
430:
Server.prototype.param = function param(name, fn) {
431:
        this.use(function _param(req, res, next) {
432:
                if (req.params && req.params[name]) {
433:
                        fn.call(this, req, res, next, req.params[name], name);
434:
                } else {
435:
                        next();
436:
                }
437:
        });
438:
 
439:
        return (this);
440:
};
441:
 
442:
 
443:
/**
444:
 * Piggy-backs on the `server.use` method. It attaches a new middleware
445:
 * function that only fires if the specified version matchtes the request.
446:
 *
447:
 * Note that if the client does not request a specific version, the middleware
448:
 * function always fires. If you don't want this set a default version with a
449:
 * pre handler on requests where the client omits one.
450:
 *
451:
 * Exposes an API:
452:
 *   server.versionedUse("version", function (req, res, next, ver) {
453:
 *     // do stuff that only applies to routes of this API version
454:
 *   });
455:
 *
456:
 * @param {String|Array} The version or versions of the URL to respond to
457:
 * @param {Function} The middleware function to execute, the fourth parameter
458:
 *                   will be the selected version
459:
 */
460:
Server.prototype.versionedUse = function versionedUse(versions, fn) {
461:
        if (!Array.isArray(versions))
462:
                versions = [versions];
463:
        assert.arrayOfString(versions, 'versions');
464:
 
465:
        versions.forEach(function (v) {
466:
                if (!semver.valid(v))
467:
                        throw new TypeError('%s is not a valid semver', v);
468:
        });
469:
 
470:
        this.use(function _versionedUse(req, res, next) {
471:
                var ver;
472:
                if (req.version() === '*' ||
473:
                    (ver = maxSatisfying(versions,
474:
                                         req.version()) || false)) {
475:
                        fn.call(this, req, res, next, ver);
476:
                } else {
477:
                        next();
478:
                }
479:
        });
480:
 
481:
        return (this);
482:
};
483:
 
484:
 
485:
/**
486:
 * Removes a route from the server.
487:
 *
488:
 * You  pass in the route 'blob' you got from a mount call.
489:
 *
490:
 * @param {String} name the route name.
491:
 * @return {Boolean} true if route was removed, false if not.
492:
 * @throws {TypeError} on bad input.
493:
 */
494:
Server.prototype.rm = function rm(route) {
495:
        var r = this.router.unmount(route);
496:
        if (r && this.routes[r])
497:
                delete this.routes[r];
498:
 
499:
        return (r);
500:
};
501:
 
502:
 
503:
/**
504:
 * Installs a list of handlers to run _before_ the "normal" handlers of all
505:
 * routes.
506:
 *
507:
 * You can pass in any combination of functions or array of functions.
508:
 *
509:
 * @throws {TypeError} on input error.
510:
 */
511:
Server.prototype.use = function use() {
512:
        var self = this;
513:
 
514:
        (argumentsToChain(arguments) || []).forEach(function (h) {
515:
                self.chain.push(h);
516:
        });
517:
 
518:
        return (this);
519:
};
520:
 
521:
 
522:
/**
523:
 * Gives you hooks to run _before_ any routes are located.  This gives you
524:
 * a chance to intercept the request and change headers, etc., that routing
525:
 * depends on.  Note that req.params will _not_ be set yet.
526:
 */
527:
Server.prototype.pre = function pre() {
528:
        var self = this;
529:
 
530:
        argumentsToChain(arguments).forEach(function (h) {
531:
                self.before.push(h);
532:
        });
533:
 
534:
        return (this);
535:
};
536:
 
537:
 
538:
Server.prototype.toString = function toString() {
539:
        var LINE_FMT = '\t%s: %s\n';
540:
        var SUB_LINE_FMT = '\t\t%s: %s\n';
541:
        var self = this;
542:
        var str = '';
543:
 
544:
        function handlersToString(arr) {
545:
                var s = '[' + arr.map(function (b) {
546:
                        return (b.name || 'function');
547:
                }).join(', ') + ']';
548:
 
549:
                return (s);
550:
        }
551:
 
552:
        str += sprintf(LINE_FMT, 'Accepts', this.acceptable.join(', '));
553:
        str += sprintf(LINE_FMT, 'Name', this.name);
554:
        str += sprintf(LINE_FMT, 'Pre', handlersToString(this.before));
555:
        str += sprintf(LINE_FMT, 'Router', this.router.toString());
556:
        str += sprintf(LINE_FMT, 'Routes', '');
557:
        Object.keys(this.routes).forEach(function (k) {
558:
                var handlers = handlersToString(self.routes[k]);
559:
                str += sprintf(SUB_LINE_FMT, k, handlers);
560:
        });
561:
        str += sprintf(LINE_FMT, 'Secure', this.secure);
562:
        str += sprintf(LINE_FMT, 'Url', this.url);
563:
        str += sprintf(LINE_FMT, 'Version', this.versions.join());
564:
 
565:
        return (str);
566:
};
567:
 
568:
 
569:
 
570:
///--- Private methods
571:
 
572:
Server.prototype._handle = function _handle(req, res) {
573:
        var self = this;
574:
 
575:
        function routeAndRun() {
576:
                self._route(req, res, function (route, context) {
577:
                        req.context = req.params = context;
578:
                        req.route = route.spec;
579:
 
580:
                        var r = route ? route.name : null;
581:
                        var chain = self.routes[r];
582:
 
583:
                        self._run(req, res, route, chain, function done(e) {
584:
                                self.emit('after', req, res, route, e);
585:
                        });
586:
                });
587:
        }
588:
 
589:
        if (this.before.length > 0) {
590:
                this._run(req, res, null, this.before, function (err) {
591:
                        if (!err) {
592:
                                routeAndRun();
593:
                        }
594:
                });
595:
        } else {
596:
                routeAndRun();
597:
        }
598:
};
599:
 
600:
 
601:
Server.prototype._route = function _route(req, res, name, cb) {
602:
        var self = this;
603:
 
604:
        if (typeof (name) === 'function') {
605:
                cb = name;
606:
                name = null;
607:
        } else {
608:
                this.router.get(name, req, function (err, route, ctx) {
609:
                        if (err) {
610:
                                emitRouteError(self, req, res, err);
611:
                        } else {
612:
                                cb(route, ctx);
613:
                        }
614:
                });
615:
        }
616:
 
617:
        this.router.find(req, res, function onRoute(err, route, ctx) {
618:
                var r = route ? route.name : null;
619:
                if (err) {
620:
                        if (optionsError(err, req, res)) {
621:
                                self.emit('after', req, res, err);
622:
                        } else {
623:
                                emitRouteError(self, req, res, err);
624:
                        }
625:
                } else if (r === 'preflight') {
626:
                        res.writeHead(200);
627:
                        res.end();
628:
                        self.emit('after', req, res, null);
629:
                } else if (!r || !self.routes[r]) {
630:
                        err = new ResourceNotFoundError(req.path());
631:
                        emitRouteError(self, res, res, err);
632:
                } else {
633:
                        cb(route, ctx);
634:
                }
635:
        });
636:
};
637:
 
638:
 
639:
// The goofy checks in next() are to make sure we fire the DTrace
640:
// probes after an error might have been sent, as in a handler
641:
// return next(new Error) is basically shorthand for sending an
642:
// error via res.send(), so we do that before firing the dtrace
643:
// probe (namely so the status codes get updated in the
644:
// response).
645:
//
646:
// Callers can stop the chain from proceding if they do
647:
// return next(false); This is useful for non-errors, but where
648:
// a response was sent and you don't want the chain to keep
649:
// going
650:
Server.prototype._run = function _run(req, res, route, chain, cb) {
651:
        var d;
652:
        var i = -1;
653:
        var id = dtrace.nextId();
654:
        var log = this.log;
655:
        var self = this;
656:
 
657:
        function next(arg) {
658:
                var done = false;
659:
                if (arg) {
660:
                        if (arg instanceof Error) {
661:
                                log.trace({err: arg}, 'next(err=%s)',
662:
                                          (arg.name || 'Error'));
663:
                                res.send(arg);
664:
                                done = true;
665:
                        } else if (typeof (arg) === 'string') {
666:
                                if (req._rstfy_chained_route) {
667:
                                        var _e = new errors.InternalError();
668:
                                        log.error({
669:
                                                err: _e
670:
                                        }, 'Multiple next("chain") calls not ' +
671:
                                                  'supported');
672:
                                        res.send(_e);
673:
                                        return (false);
674:
                                }
675:
 
676:
                                self._route(req, res, arg, function (r, ctx) {
677:
                                        req.context = req.params = ctx;
678:
                                        req.route = r.spec;
679:
 
680:
                                        var _c = chain.slice(0, i + 1);
681:
                                        function _uniq(fn) {
682:
                                                return (_c.indexOf(fn) === -1);
683:
                                        }
684:
 
685:
                                        var _routes = self.routes[r.name] || [];
686:
                                        var _chain = _routes.filter(_uniq);
687:
 
688:
                                        req._rstfy_chained_route = true;
689:
                                        self._run(req, res, r, _chain, cb);
690:
                                });
691:
                        }
692:
                }
693:
 
694:
                if (arg === false)
695:
                        done = true;
696:
 
697:
                // Fire DTrace done for the previous handler.
698:
                if ((i + 1) > 0 && chain[i] && !chain[i]._skip) {
699:
                        dtrace._rstfy_probes['handler-done'].fire(function () {
700:
                                return ([
701:
                                        self.name,
702:
                                        route !== null ? route : 'pre',
703:
                                        chain[i].name || ('handler-' + i),
704:
                                        id
705:
                                ]);
706:
                        });
707:
                }
708:
 
709:
                // Run the next handler up
710:
                if (!done && chain[++i]) {
711:
                        if (chain[i]._skip)
712:
                                return (next());
713:
 
714:
                        if (log.trace())
715:
                                log.trace('running %s', chain[i].name || '?');
716:
 
717:
                        dtrace._rstfy_probes['handler-start'].fire(function () {
718:
                                return ([
719:
                                        self.name,
720:
                                        route !== null ? route : 'pre',
721:
                                        chain[i].name || ('handler-' + i),
722:
                                        id
723:
                                ]);
724:
                        });
725:
 
726:
                        var n = once(next);
727:
                        n.ifError = ifError(n);
728:
                        return (chain[i].call(self, req, res, n));
729:
                }
730:
 
731:
                dtrace._rstfy_probes['route-done'].fire(function () {
732:
                        return ([
733:
                                self.name,
734:
                                route !== null ? route : 'pre',
735:
                                id,
736:
                                res.statusCode || 200,
737:
                                res.headers()
738:
                        ]);
739:
                });
740:
 
741:
                if (route === null) {
742:
                        self.emit('preDone', req, res);
743:
                } else {
744:
                        self.emit('done', req, res, route);
745:
                }
746:
 
747:
                return (cb ? cb(arg) : true);
748:
        }
749:
        var n1 = once(next);
750:
        n1.ifError = ifError(n1);
751:
 
752:
        dtrace._rstfy_probes['route-start'].fire(function () {
753:
                return ([
754:
                        self.name,
755:
                        route !== null ? route : 'pre',
756:
                        id,
757:
                        req.method,
758:
                        req.href(),
759:
                        req.headers
760:
                ]);
761:
        });
762:
 
763:
        d = domain.create();
764:
        d.add(req);
765:
        d.add(res);
766:
        d.on('error', function onError(err) {
767:
                if (err._restify_next) {
768:
                        err._restify_next(err);
769:
                } else {
770:
                        log.trace({err: err}, 'uncaughtException');
771:
                        self.emit('uncaughtException', req, res, route, err);
772:
                }
773:
        });
774:
        d.run(n1);
775:
};
776:
 
777:
 
778:
Server.prototype._setupRequest = function _setupRequest(req, res) {
779:
        req.log = res.log = this.log;
780:
        req._time = res._time = Date.now();
781:
 
782:
        res.acceptable = this.acceptable;
783:
        res.formatters = this.formatters;
784:
        res.req = req;
785:
        res.serverName = this.name;
786:
        res.version = this.router.versions[this.router.versions.length - 1];
787:
};
788:
 
789:
// vim: set et ts=8 sts=8 sw=8: