forked from HubSpot/BuckyServer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.coffee
executable file
·147 lines (112 loc) · 3.97 KB
/
server.coffee
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env coffee
Q = require 'q'
_ = require 'underscore'
express = require 'express'
http = require 'http'
# Set cwd for config, and load config file
process.chdir __dirname
config = require 'config'
configWrapper = require './lib/configWrapper'
load = require './lib/load'
MODULES = config.modules
loadLogger = ->
if MODULES.logger
load MODULES.logger, {config}
else
console
# We always have the base config, but the
# app can optionally swap it out for something else.
loadConfig = (logger) ->
if MODULES.config
load MODULES.config, {config, logger}
else
configWrapper config
setCORSHeaders = (req, res, next) ->
res.setHeader 'Access-Control-Allow-Origin', '*'
res.setHeader 'Access-Control-Allow-Methods', 'POST'
res.setHeader 'Access-Control-Max-Age', '604800'
res.setHeader 'Access-Control-Allow-Credentials', 'true'
res.setHeader 'Access-Control-Allow-Headers', 'content-type'
next()
setJSONHeader = (req, res, next) ->
req.headers['content-type'] = 'application/json'
next()
parser = (req, res, next) ->
buf = ''
req.body = {}
req.setEncoding 'utf8'
req.on 'data', (chunk) ->
buf += chunk
req.on 'end', ->
metrics = buf.split('\n')
for metric in metrics
[name, value] = metric.split(':')
if name and value
req.body[name] = value
next()
loadApp = (logger, loadedConfig) ->
app = express()
APP_ROOT = process.env.APP_ROOT ? loadedConfig.get('server.appRoot').get() ? ''
moduleGroups = {}
loadModuleGroup = (group) ->
moduleGroups[group] = {}
if MODULES[group]
_.map MODULES[group], (name) ->
logger.log "Loading #{ group } Module", name
try
promise = load name, {logger, app, config: loadedConfig}
catch e
console.log "Error loading module", e?.stack
promise.then (ret) ->
logger.log name, "Ready"
moduleGroups[group][name] = ret
promise
else
[]
appPromises = loadModuleGroup 'app'
Q.all(appPromises).then ->
logger.log "Binding Routes at %s", (APP_ROOT or '/')
# Allow modules to bind to any number of endpoints
# Most should simply bind to "send"
routes = {}
for name, _routes of moduleGroups.app
continue if not _routes?
if _.isFunction _routes
_routes = {send: _routes}
for path, handler of _routes
route = "#{ APP_ROOT }/v1/#{ path }"
if not routes[route]?
routes[route] = [handler]
else
routes[route].push handler
for path, handlers of routes
# Bind all request modules as middleware and install the collectors
app.post "#{ path }/json", setJSONHeader, express.json(), setCORSHeaders, handlers...
app.post path, parser, setCORSHeaders, handlers...
app.options path, setCORSHeaders, (req, res) ->
res.send 200, ''
app.get "#{ APP_ROOT }/v1/health-check", (req, res) ->
res.send('OK\n')
if loadedConfig.get('server.https.options').get() instanceof Object
https = require 'https'
fs = require 'fs'
httpsOptions = _.mapObject loadedConfig.get('server.https.options').get(), (v, k) ->
if _.isObject v and _.has v, 'filePath'
try
fs.readFileSync v.filePath
catch e
logger.error "Unable to load file: " + v.filePath, e
else
v
httpsPort = loadedConfig.get('server.https.port').get() ? (port + 1)
https.createServer(httpsOptions, app).listen httpsPort
logger.log "HTTPS Server listening on port %d in %s mode", httpsPort, app.settings.env
if !loadedConfig.get('server.httpsOnly').get()
port = process.env.PORT ? loadedConfig.get('server.port').get() ? 5000
http.createServer(app).listen port
logger.log 'HTTP Server listening on port %d in %s mode', port, app.settings.env
Q.when(loadLogger()).then (logger) ->
logger.log "Loading Config"
Q.when(loadConfig logger).then (loadedConfig) ->
logger.log "Loading App"
loadApp(logger, loadedConfig)