-
Notifications
You must be signed in to change notification settings - Fork 1
/
server-builder.js
113 lines (88 loc) · 3.12 KB
/
server-builder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
var restify = require('restify')
var q = require('q')
var errorAdapter = require('error-adapter')
var loggerBuilder = require('logger-json-stderr')
module.exports = function(originalOpts) {
throwIfRequiredFieldsMissing([ 'port', 'name', 'routes' ], originalOpts)
var opts = mergeWithDefaults(originalOpts)
var server = opts.server = restify.createServer(opts)
opts.middleware(server)
opts.routes(opts)
server.on('listening', logPortOnStartup)
server.on('error', logErrorOnStartup)
server.on('after', opts.logAfterResponseSent)
if (opts.logBeforeRouting) { server.pre( logRequestBeforeRouting ) }
return {
server: server,
start: startServer
}
function startServer(cb){
var deferred = q.defer()
server.on('listening', returnPortToCallbackOrPromise)
server.on('error', handleStartupError)
server.listen(opts.port)
return deferred.promise
function returnPortToCallbackOrPromise() {
var port = server.address().port
deferred.resolve({ port: port })
if (cb) { cb(null, { port: port }) }
}
function handleStartupError(err) {
deferred.reject(err)
if (cb) { cb(err) }
}
}
function mergeWithDefaults(src) {
var opts = shallowCopy(src)
if (!opts.middleware) { opts.middleware = addMiddleware }
if (!opts.log) { opts.log = loggerBuilder({ name: opts.name, style: 'bunyan' }) }
if (!opts.logThis) { opts.logThis = logThisDefault }
if (!opts.logAfterResponseSent) { opts.logAfterResponseSent = logAfterResponseSentDefault }
return opts
}
function addMiddleware(server) {
server.use(restify.bodyParser({ mapParams: true }))
server.use(restify.requestLogger())
server.use(restify.fullResponse())
}
function logPortOnStartup() {
var port = server.address().port
server.log.info({ port: port }, 'success: server start')
if (typeof opts.postStart == 'function') { opts.postStart() }
}
function logErrorOnStartup(err) {
server.log.error({ error: err, port: opts.port }, 'fail: server start')
}
function logRequestBeforeRouting(req, res, next) {
req.log.info({req: req}, "HTTP request: before Routing");
return next()
}
function logAfterResponseSentDefault(req, res, route, error) {
var logThis = opts.logThis(req, res, route, error)
if (!error) { return req.log.info(logThis, "HTTP response") }
return req.log.error(logThis, "HTTP response")
}
}
function logThisDefault(req, res, route, error) {
var logTheseThings = {
req: req,
res: res,
route: route
}
if (error) { logTheseThings.error = error }
return logTheseThings
}
function throwIfRequiredFieldsMissing(required, opts) {
if (typeof opts != 'object') { throw errorAdapter.create({ message: 'must pass in an object' }) }
var missing = required.filter(function(field) {
return opts[field] === undefined || opts[field] === null
})
if (missing.length > 0) { throw errorAdapter.create({message: 'required field missing: ' + missing.join(','), missing: missing }) }
}
function shallowCopy(src) {
var dest = {}
for(var key in src) {
if(src.hasOwnProperty(key)) { dest[key] = src[key] }
}
return dest
}