forked from igroff/epiquery2-orig
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathepistream.coffee
More file actions
executable file
·144 lines (123 loc) · 4.64 KB
/
Copy pathepistream.coffee
File metadata and controls
executable file
·144 lines (123 loc) · 4.64 KB
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
#! /usr/bin/env ./node_modules/.bin/coffee
# vim:ft=coffee
cluster = require 'cluster'
express = require 'express'
_ = require 'underscore'
path = require 'path'
log = require 'simplog'
sockjs = require 'sockjs'
http = require 'http'
Context = require('./src/context').Context
core = require './src/core.coffee'
config = require './src/config.coffee'
sockjsClient = require './src/transport/sockjs.coffee'
httpClient = require './src/transport/http.coffee'
queryRequestHandler = require('./src/request.coffee').queryRequestHandler
app = express()
app.use express.favicon()
app.use express.bodyParser()
app.use '/static', express.static(path.join(__dirname, 'static'))
app.use app.router
app.use express.errorHandler()
apiKey = config.epistreamApiKey
socketServer = sockjs.createServer(app, options: disconnect_delay: 900000)
# initialize the core including driver loading, etc.
core.init()
if config.isDevelopmentMode()
log.warn "epiquery2 running in development mode, this will cause requests to be slower"
set_cors_headers = (req, res, next) ->
res.header 'Access-Control-Allow-Origin', req.get('Origin') ? '*'
res.header 'Access-Control-Allow-Credentials', true
res.header 'Access-Control-Allow-Headers', 'Content-Type'
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
next()
app.use set_cors_headers
app.all '*', set_cors_headers
app.options '*', (req, res) ->
res.status(200).send()
app.get '/diagnostic', (req, res) ->
response =
message: "ok"
connections: _.pluck(config.connections, 'name')
if config.isDevelopmentMode
response.aclsEnabled = config.enableTemplateAcls
res.send response
app.get '/templates', (req, res) ->
response =
templates: []
res.send response
app.get '/stats', (req, res) ->
stats =
# execution time data is a object contiaining
# "templateName": <CircularBuffer of recent exedution times>
# properties
recentExecutionTimes: _.map core.getQueryExecutionTimes, (v, k, l) ->
ret = {}
ret[k] = "#{v}"
ret
recentQueries: core.QueryStats.buffer.getEntries()
inflightQueries: core.getInflightQueries()
serverTime: new Date()
res.send stats
httpRequestHandler = (req, res) ->
clientId = req.param 'client_id'
c = new Context()
c.queryId = req.param 'queryId'
_.extend c, httpClient.getQueryRequestInfo(req, !!apiKey)
# Check that the client supplied key matches server key
if apiKey
if !(c.clientKey == apiKey)
log.error "Unauthorized HTTP Access Attempted from IP: #{req.connection.remoteAddress}"
log.error "Unauthorized Context: #{JSON.stringify(c.templateContext)}"
res.send error: "Unauthorized Access"
return
if c.connectionName and not config.connections[c.connectionName]
res.send error: "unable to find connection by name '#{c.connectionName}'"
return
httpClient.attachResponder c, res
c.requestedTemplatePath = req.path
queryRequestHandler(c)
socketServer.on 'connection', (conn) ->
conn.on 'data', (message) ->
if apiKey
if !~ conn.url.indexOf apiKey
conn.close()
log.error "Unauthorized Socket Access Attempted from IP: #{conn.remoteAddress}"
log.error "Unauthorized Context: #{JSON.stringify(message)}"
return
log.debug "inbound message #{message}"
if message == 'ping'
conn.write 'pong'
return
message = JSON.parse(message)
ctxParms =
templateName: message.templateName
closeOnEnd: message.closeOnEnd
connectionName: message.connectionName
queryId: message.queryId
templateContext: message.data
requestHeaders: conn.headers
ctxParms.debug if message.debug
context = new Context(ctxParms)
log.debug "[q:#{context.queryId}] starting processing"
sockjsClient.attachResponder(context, conn)
queryRequestHandler(context)
conn.on 'error', (e) ->
log.error "error on connection", e
conn.on 'close', () ->
log.debug "sockjs client disconnected"
socketServer.on 'error', (e) ->
log.error "error on socketServer", e
app.get /\/(.+)$/, httpRequestHandler
app.post /\/(.+)$/, httpRequestHandler
log.debug "server worker process starting with configuration"
log.info "%j", config
log.debug "node version", process.version
server = http.createServer(app)
# use key based prefix if key is in url
prefix = {prefix: '/sockjs'}
prefix.prefix = "/#{apiKey}/sockjs" if apiKey && config.urlBasedApiKey
socketServer.installHandlers(server, prefix)
Cluster = require 'cluster2'
cluster = new Cluster(port: config.port, noWorkers:config.forks, timeout:config.httpRequestTimeoutInSeconds * 1000)
cluster.listen (cb) -> cb(server)