qiprofile
Version:
Quantitative Imaging Profile ( QiPr) web application
158 lines (137 loc) • 4.63 kB
text/coffeescript
#
# The Imaging Profile Express server application.
#
express = require 'express'
http = require 'http'
path = require 'path'
mkdirp = require 'mkdirp'
net = require 'net'
fs = require 'fs'
logger = require 'express-bunyan-logger'
forever = require 'forever-monitor'
authenticate = require 'authenticate'
spawn = require './spawn'
favicon = require 'serve-favicon'
bodyParser = require 'body-parser'
serveStatic = require 'serve-static'
methodOverride = require 'method-override'
errorHandler = require 'errorhandler'
# The port assignments.
PORT = 3000
PORT_TEST = PORT + 1
MONGODB_PORT = 27017
EVE_PORT = 5000
# The grunt build tasks place all compiled and copied files within
# the _public directory.
root = path.join(__dirname, '..', '_public')
# Rewrite all server /api requests to the REST server
# on the default REST host and port.
api = require './api'
# The Express server.
server = express()
# Set the port.
server.set 'port', process.env.PORT or PORT
# The run environment.
env = server.get('env') or 'production'
# @returns /var/log/qiprofile.log, if it is writable,
# ./log/qiprofile.log otherwise
defaultLogFile = ->
try
fd = fs.openSync('/var/log/qiprofile.log', 'w')
fs.closeSync(fd)
'/var/log/qiprofile.log'
catch err
'./log/qiprofile.log'
# The log file is either set in the environment or defaults to
# log/qiprofile.log in the current directory.
relLogFile = server.get('log') or defaultLogFile()
logFile = path.resolve(relLogFile)
logDir = path.dirname(logFile)
mkdirp(logDir)
# If the server has the debug flag set, then the log level is debug.
# Otherwise, the log level is inferred from the environment.
if server.get('debug') or env is not 'production'
logLevel = 'debug'
else
logLevel = 'info'
# The logger configuration.
logConfig =
name: 'qiprofile'
streams: [
level: logLevel, path: logFile
]
# Enable the middleware.
server.use favicon(root + '/media/favicon.ico')
server.use bodyParser.json()
server.use bodyParser.urlencoded(extended: true)
server.use methodOverride()
server.use logger(logConfig)
server.use serveStatic(root)
server.use authenticate.middleware(
encrypt_key: 'Pa2#a'
validate_key: 'Fir@n2e'
)
# Authenticate.
# Note: authentication is not enabled by default.
server.get '/login', (req, res) ->
res.writeHead 200, ContentType: 'application/json'
res.write JSON.stringify(
'access_token': authenticate.serializeToken(req.data.client_id,
req.data.user_id)
)
res.end
# The API route.
restUrl = process.env.QIREST_HOST or 'localhost'
server.use '/api', api(restUrl)
# Serve the static files from root.
server.get '/static/*', (req, res) ->
path = root + req.path.replace('/static', '')
res.sendFile path
# Serve the partial HTML files.
server.get '/partials/*', (req, res) ->
res.sendFile "#{root}/#{req.path}.html"
# Since qiprofile is an Angular Single-Page Application,
# serve index for all quip routes. The qiprofile
# application then resolves the URL on the client
# and requests the partial.
server.get '/quip*', (req, res) ->
res.sendFile "#{root}/index.html"
# Kludge to work around repeat requests. See the app
# error.coffee FIXME.
lastErrorMsg = null
server.post '/error', (req, res) ->
# Print the error.
if req.body.message != lastErrorMsg
console.log("Client error: #{ req.body.message }")
console.log("See the log at #{ logFile }")
# Log the error.
req.log.info(req.body)
# Send default status code 200 with a 'Logged' message.
lastErrorMsg = req.body.message
res.send('Logged')
# Development error handling.
if env is 'development'
server.use errorHandler()
server.set 'pretty', true
# The test port.
if env is 'test'
server.set 'port', PORT_TEST
# Callback invoked after MongoDB is started.
mongod_callback = ->
# The REST server start mode, production or development.
restMode = if env is 'test' then 'development' else env
# The REST server command.
cmd = if restMode? then "qirest --#{ restMode }" else 'qirest'
# The callback after the REST server is started.
eve_callback = ->
#...then the Express server.
port = server.get 'port'
http.createServer(server).listen port, ->
env = server.settings.env
console.log "The qiprofile server is listening on port #{port}" +
" in #{env} mode."
# Start the REST app without logging to the console.
spawn(cmd, EVE_PORT, eve_callback, {silent: true})
# Start MongoDB, if necessary, and forward to the callback.
spawn('mongod', MONGODB_PORT, mongod_callback, {silent: true})
module.exports = server