2014-02-14 11:39:05 -05:00
|
|
|
express = require('express')
|
|
|
|
logger = require('logger-sharelatex')
|
|
|
|
logger.initialize("filestore")
|
|
|
|
settings = require("settings-sharelatex")
|
|
|
|
request = require("request")
|
|
|
|
fileController = require("./app/js/FileController")
|
2018-07-04 06:18:55 -04:00
|
|
|
bucketController = require("./app/js/BucketController")
|
2014-02-14 11:39:05 -05:00
|
|
|
keyBuilder = require("./app/js/KeyBuilder")
|
2016-12-14 11:47:53 -05:00
|
|
|
healthCheckController = require("./app/js/HealthCheckController")
|
2014-02-14 11:39:05 -05:00
|
|
|
domain = require("domain")
|
|
|
|
appIsOk = true
|
|
|
|
app = express()
|
|
|
|
|
2018-09-11 05:51:10 -04:00
|
|
|
if settings.sentry?.dsn?
|
|
|
|
logger.initializeErrorReporting(settings.sentry.dsn)
|
2018-09-06 12:01:18 -04:00
|
|
|
|
2014-05-09 08:30:35 -04:00
|
|
|
Metrics = require "metrics-sharelatex"
|
|
|
|
Metrics.initialize("filestore")
|
|
|
|
Metrics.open_sockets.monitor(logger)
|
2015-06-23 08:41:14 -04:00
|
|
|
Metrics.event_loop?.monitor(logger)
|
2015-08-18 10:36:07 -04:00
|
|
|
Metrics.memory.monitor(logger)
|
2014-02-14 11:39:05 -05:00
|
|
|
|
|
|
|
app.configure ->
|
2014-05-09 08:30:35 -04:00
|
|
|
app.use Metrics.http.monitor(logger)
|
2018-07-04 06:18:55 -04:00
|
|
|
|
2014-02-14 11:39:05 -05:00
|
|
|
app.configure 'development', ->
|
|
|
|
console.log "Development Enviroment"
|
|
|
|
app.use express.errorHandler({ dumpExceptions: true, showStack: true })
|
|
|
|
|
|
|
|
app.configure 'production', ->
|
|
|
|
console.log "Production Enviroment"
|
|
|
|
app.use express.errorHandler()
|
|
|
|
|
2014-05-09 08:30:35 -04:00
|
|
|
Metrics.inc "startup"
|
2014-02-14 11:39:05 -05:00
|
|
|
|
|
|
|
app.use (req, res, next)->
|
2014-05-09 08:30:35 -04:00
|
|
|
Metrics.inc "http-request"
|
2014-02-14 11:39:05 -05:00
|
|
|
next()
|
|
|
|
|
|
|
|
app.use (req, res, next) ->
|
|
|
|
requestDomain = domain.create()
|
|
|
|
requestDomain.add req
|
|
|
|
requestDomain.add res
|
|
|
|
requestDomain.on "error", (err)->
|
2014-12-23 11:49:34 -05:00
|
|
|
try
|
|
|
|
# request a shutdown to prevent memory leaks
|
|
|
|
beginShutdown()
|
2014-05-12 10:45:15 -04:00
|
|
|
if !res.headerSent
|
2014-12-23 11:49:34 -05:00
|
|
|
res.send(500, "uncaught exception")
|
|
|
|
logger = require('logger-sharelatex')
|
|
|
|
req =
|
|
|
|
body:req.body
|
|
|
|
headers:req.headers
|
|
|
|
url:req.url
|
|
|
|
key: req.key
|
|
|
|
statusCode: req.statusCode
|
|
|
|
err =
|
|
|
|
message: err.message
|
|
|
|
stack: err.stack
|
|
|
|
name: err.name
|
|
|
|
type: err.type
|
|
|
|
arguments: err.arguments
|
|
|
|
logger.err err:err, req:req, res:res, "uncaught exception thrown on request"
|
|
|
|
catch exception
|
|
|
|
logger.err err: exception, "exception in request domain handler"
|
2014-02-14 11:39:05 -05:00
|
|
|
requestDomain.run next
|
|
|
|
|
2014-12-23 11:46:31 -05:00
|
|
|
app.use (req, res, next) ->
|
|
|
|
if not appIsOk
|
|
|
|
# when shutting down, close any HTTP keep-alive connections
|
|
|
|
res.set 'Connection', 'close'
|
|
|
|
next()
|
|
|
|
|
2015-01-05 11:56:19 -05:00
|
|
|
app.get "/project/:project_id/file/:file_id", keyBuilder.userFileKey, fileController.getFile
|
|
|
|
app.post "/project/:project_id/file/:file_id", keyBuilder.userFileKey, fileController.insertFile
|
|
|
|
|
2015-11-25 12:01:19 -05:00
|
|
|
app.put "/project/:project_id/file/:file_id", keyBuilder.userFileKey, express.bodyParser(), fileController.copyFile
|
2014-02-14 11:39:05 -05:00
|
|
|
app.del "/project/:project_id/file/:file_id", keyBuilder.userFileKey, fileController.deleteFile
|
|
|
|
|
|
|
|
app.get "/template/:template_id/v/:version/:format", keyBuilder.templateFileKey, fileController.getFile
|
2015-04-09 12:14:47 -04:00
|
|
|
app.get "/template/:template_id/v/:version/:format/:sub_type", keyBuilder.templateFileKey, fileController.getFile
|
2014-02-14 11:39:05 -05:00
|
|
|
app.post "/template/:template_id/v/:version/:format", keyBuilder.templateFileKey, fileController.insertFile
|
|
|
|
|
2015-05-08 10:15:48 -04:00
|
|
|
|
|
|
|
app.get "/project/:project_id/public/:public_file_id", keyBuilder.publicFileKey, fileController.getFile
|
|
|
|
app.post "/project/:project_id/public/:public_file_id", keyBuilder.publicFileKey, fileController.insertFile
|
|
|
|
|
2015-11-25 12:01:19 -05:00
|
|
|
app.put "/project/:project_id/public/:public_file_id", keyBuilder.publicFileKey, express.bodyParser(), fileController.copyFile
|
2015-05-08 10:15:48 -04:00
|
|
|
app.del "/project/:project_id/public/:public_file_id", keyBuilder.publicFileKey, fileController.deleteFile
|
|
|
|
|
2016-03-13 15:22:14 -04:00
|
|
|
app.get "/project/:project_id/size", keyBuilder.publicProjectKey, fileController.directorySize
|
2016-03-11 20:31:46 -05:00
|
|
|
|
2018-07-04 06:18:55 -04:00
|
|
|
app.get "/bucket/:bucket/key/*", bucketController.getFile
|
|
|
|
|
2014-11-27 08:48:39 -05:00
|
|
|
app.get "/heapdump", (req, res)->
|
|
|
|
require('heapdump').writeSnapshot '/tmp/' + Date.now() + '.filestore.heapsnapshot', (err, filename)->
|
|
|
|
res.send filename
|
|
|
|
|
2014-02-14 11:39:05 -05:00
|
|
|
app.post "/shutdown", (req, res)->
|
|
|
|
appIsOk = false
|
|
|
|
res.send()
|
|
|
|
|
|
|
|
app.get '/status', (req, res)->
|
|
|
|
if appIsOk
|
|
|
|
res.send('filestore sharelatex up')
|
|
|
|
else
|
|
|
|
logger.log "app is not ok - shutting down"
|
|
|
|
res.send("server is being shut down", 500)
|
|
|
|
|
2016-12-14 11:47:53 -05:00
|
|
|
|
|
|
|
app.get "/health_check", healthCheckController.check
|
|
|
|
|
2014-02-14 11:39:05 -05:00
|
|
|
|
|
|
|
app.get '*', (req, res)->
|
|
|
|
res.send 404
|
|
|
|
|
2014-12-23 11:48:11 -05:00
|
|
|
server = require('http').createServer(app)
|
|
|
|
port = settings.internal.filestore.port or 3009
|
|
|
|
host = settings.internal.filestore.host or "localhost"
|
2014-02-14 11:39:05 -05:00
|
|
|
|
2014-12-23 11:48:11 -05:00
|
|
|
beginShutdown = () ->
|
2014-12-23 11:55:34 -05:00
|
|
|
if appIsOk
|
|
|
|
appIsOk = false
|
2015-01-07 05:26:30 -05:00
|
|
|
# hard-terminate this process if graceful shutdown fails
|
|
|
|
killTimer = setTimeout () ->
|
|
|
|
process.exit 1
|
|
|
|
, 120*1000
|
|
|
|
killTimer.unref?() # prevent timer from keeping process alive
|
|
|
|
server.close () ->
|
|
|
|
logger.log "closed all connections"
|
|
|
|
Metrics.close()
|
|
|
|
process.disconnect?()
|
2014-12-23 11:55:34 -05:00
|
|
|
logger.log "server will stop accepting connections"
|
2014-12-23 11:48:11 -05:00
|
|
|
|
|
|
|
server.listen port, host, ->
|
2015-04-30 10:04:55 -04:00
|
|
|
logger.info "Filestore starting up, listening on #{host}:#{port}"
|
2015-01-07 05:28:47 -05:00
|
|
|
|
|
|
|
process.on 'SIGTERM', () ->
|
|
|
|
logger.log("filestore got SIGTERM, shutting down gracefully")
|
|
|
|
beginShutdown()
|
2015-08-05 11:52:01 -04:00
|
|
|
|
|
|
|
if global.gc?
|
|
|
|
gcTimer = setInterval () ->
|
|
|
|
global.gc()
|
|
|
|
logger.log process.memoryUsage(), "global.gc"
|
|
|
|
, 3 * oneMinute = 60 * 1000
|
|
|
|
gcTimer.unref()
|