-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
183 lines (153 loc) Β· 5.26 KB
/
main.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
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* Heinrich - Reverse proxy
* Copyright(c) 2016-present @GavinDmello
* BSD Licensed
*/
var Pfade = require('pfade')
var pfade = new Pfade(__dirname)
var cluster = require('cluster')
var numCPUs = require('os').cpus().length;
var config = pfade.require('./config.json')
var loggerUtility = pfade.require('utilities/logger')
var logger = new loggerUtility()
var genericUtility = pfade.require('utilities/generic-utility')
var PORT = config.port || 3001
var router = pfade.require('lib/router')
var SocketServer = pfade.require('lib/socket-server')
var socketServer = new SocketServer()
var RateLimiter = pfade.require('lib/rate-limiter')
var showArt = pfade.require('lib/art')
var rateLimiter
var nextTick = process.nextTick
var pid = process.pid
var server, http
var regexForIPV6 = /^.*:/
cluster.schedulingPolicy = cluster.SCHED_RR
if (config.multiCore) {
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++) {
// Create a worker
var worker = cluster.fork()
worker.on('message', handleAction)
}
showArt()
handleAnalytics(numCPUs)
// restart if process dies
cluster.on('exit', function exitCode(worker, code, signal) {
logger.log('Worker died, restarting. check error logs')
logger.error('worker dead', code, signal)
cluster.fork()
})
setTimeout(function() {
logger.log('starting server in multi core mode!')
logger.log('creating', numCPUs, ' processes')
}, 1000)
} else {
serverInit({ clusterId: cluster.worker.id })
}
} else {
showArt()
handleAnalytics(1)
setTimeout(function() {
logger.log('starting server without worker processes')
}, 1000)
serverInit({}) // No cluster present so no Id
}
// Initializing the server
function serverInit(opts) {
// request handler
function handleAnyRequest(request, response) {
if (config.requestTimeout) {
request.connection.setTimeout(config.requestTimeout * 1000)
}
var clientIp = request.headers['x-forwarded-for'] ||
request.connection.remoteAddress ||
request.socket.remoteAddress ||
request.connection.socket.remoteAddress
clientIp = clientIp.replace(regexForIPV6, '')
var clientAddressIndex = config.blackListAddress.indexOf(clientIp)
var userAgent = request.headers['user-agent']
var blockedUserAgent = config.blockedUserAgent
if ((clientAddressIndex > -1) || (blockedUserAgent.indexOf(userAgent) > -1)) {
response.writeHead(500)
response.end()
return
}
if (!config.rateLimit) { // No rate limiting
forwardRequest(request, response)
return
}
var rateLimitedRoutes = config.rateLimit.rateLimitedRoutes
if (rateLimitedRoutes && rateLimitedRoutes.indexOf(request.url) > -1) {
if (!rateLimiter) rateLimiter = new RateLimiter()
var clientHash = clientIp + request.url
rateLimiter.checkRequestForRate({
clientHash: clientHash,
request: request,
response: response
}, rateLimitResponse)
} else {
forwardRequest(request, response)
}
}
// forward request to the router
function forwardRequest(request, response) {
// publish request forwarded key
request.id = opts.clusterId || undefined
router.hitServers(request, function getResponse(lbResponse) {
response.writeHead(lbResponse.statusCode)
if (lbResponse) {
response.end(lbResponse.body)
} else {
response.end()
}
})
}
// handle response from rate limit handler
function rateLimitResponse(params) {
var request = params.request
var response = params.response
if (params.forward) {
forwardRequest(request, response)
} else {
response.writeHead(503) // server not available as rate limiting is on
response.end()
}
}
// start a http/https server depending on your needs
if (config.https) {
var fs = require('fs')
http = require('https')
if (!config.key || !config.cert) {
logger.error('certificated not provided, Please test the key & certificate')
process.exit(2)
}
var options = {
key: fs.readFileSync(config.key),
cert: fs.readFileSync(config.cert)
}
server = http.createServer(options, handleAnyRequest)
} else {
http = require('http')
server = http.createServer(handleAnyRequest)
}
server.listen(PORT, function() {
logger.log("Server listening on", PORT)
})
}
// handle the action emitted by the client processes
function handleAction(msg) {
genericUtility.handleAction(msg)
}
// handle analytics
function handleAnalytics(processes) {
if (config.analytics && config.analytics.port) {
socketServer.startServer({
pid: pid,
processes: processes,
timeStamp: Date.now(),
version: pfade.require('package.json').version
})
}
}
module.exports = server