2014-02-12 12:27:43 -05:00
CompileController = require " ./app/js/CompileController "
Settings = require " settings-sharelatex "
logger = require " logger-sharelatex "
logger . initialize ( " clsi " )
smokeTest = require " smoke-test-sharelatex "
2014-10-28 08:07:17 -04:00
Path = require " path "
2014-12-04 17:07:37 -05:00
fs = require " fs "
2014-10-28 08:07:17 -04:00
2014-05-09 09:55:37 -04:00
Metrics = require " metrics-sharelatex "
Metrics . initialize ( " clsi " )
Metrics . open_sockets . monitor ( logger )
2014-02-12 12:27:43 -05:00
ProjectPersistenceManager = require " ./app/js/ProjectPersistenceManager "
2015-02-27 08:16:01 -05:00
OutputCacheManager = require " ./app/js/OutputCacheManager "
2014-02-12 12:27:43 -05:00
require ( " ./app/js/db " ) . sync ( )
express = require " express "
2014-05-19 07:18:57 -04:00
bodyParser = require " body-parser "
2014-02-12 12:27:43 -05:00
app = express ( )
2014-05-09 09:55:37 -04:00
app . use Metrics . http . monitor ( logger )
2014-05-22 07:18:56 -04:00
# Compile requests can take longer than the default two
# minutes (including file download time), so bump up the
# timeout a bit.
2014-10-17 05:14:23 -04:00
TIMEOUT = 6 * 60 * 1000
2014-05-22 07:18:56 -04:00
app . use (req, res, next) ->
req . setTimeout TIMEOUT
res . setTimeout TIMEOUT
next ( )
2014-05-19 15:03:05 -04:00
app . post " /project/:project_id/compile " , bodyParser . json ( limit: " 5mb " ) , CompileController . compile
2014-05-19 07:18:57 -04:00
app . delete " /project/:project_id " , CompileController . clearCache
2014-02-12 12:27:43 -05:00
2014-04-08 10:18:56 -04:00
app . get " /project/:project_id/sync/code " , CompileController . syncFromCode
app . get " /project/:project_id/sync/pdf " , CompileController . syncFromPdf
2015-02-25 12:05:19 -05:00
url = require " url "
staticForbidSymLinks = (root, options) ->
expressStatic = express . static root , options
basePath = Path . resolve ( root )
return (req, res, next) ->
path = url . parse ( req . url ) . pathname
requestedFsPath = Path . normalize ( " #{ basePath } / #{ path } " )
fs . realpath requestedFsPath , (err, realFsPath)->
if err ?
return res . send ( 500 )
else if requestedFsPath != realFsPath
logger . warn requestedFsPath : requestedFsPath , realFsPath : realFsPath , path: req . params [ 0 ] , project_id: req . params . project_id , " trying to access a different file (symlink), aborting "
return res . send ( 404 )
else
expressStatic ( req , res , next )
staticServer = staticForbidSymLinks Settings . path . compilesDir , setHeaders: (res, path, stat) ->
2014-10-28 08:07:17 -04:00
if Path . basename ( path ) == " output.pdf "
res . set ( " Content-Type " , " application/pdf " )
2014-12-02 09:30:13 -05:00
# Calculate an etag in the same way as nginx
# https://github.com/tj/send/issues/65
etag = (path, stat) ->
' " ' + Math . ceil ( + stat . mtime / 1000 ) . toString ( 16 ) +
' - ' + Number ( stat . size ) . toString ( 16 ) + ' " '
res . set ( " Etag " , etag ( path , stat ) )
2014-10-28 08:07:17 -04:00
else
# Force plain treatment of other file types to prevent hosting of HTTP/JS files
# that could be used in same-origin/XSS attacks.
res . set ( " Content-Type " , " text/plain " )
2014-12-02 09:30:13 -05:00
2014-12-04 18:54:22 -05:00
app . get " /project/:project_id/output/* " , require ( " ./app/js/SymlinkCheckerMiddlewear " ) , (req, res, next) ->
2015-02-27 08:16:01 -05:00
if req . query ? . build ? && req . query . build . match ( OutputCacheManager . BUILD_REGEX )
req.url = " / #{ req . params . project_id } / " + OutputCacheManager . path ( req . query . build ) + " / #{ req . params [ 0 ] } "
2015-02-25 12:05:19 -05:00
else
req.url = " / #{ req . params . project_id } / #{ req . params [ 0 ] } "
2014-12-04 18:54:22 -05:00
staticServer ( req , res , next )
2014-02-12 12:27:43 -05:00
app . get " /status " , (req, res, next) ->
res . send " CLSI is alive \n "
2014-06-05 10:51:24 -04:00
resCacher =
contentType : (@setContentType)->
send : (@code, @body)->
2014-06-05 11:13:06 -04:00
#default the server to be down
code : 500
body : { }
setContentType : " application/json "
2014-08-19 07:11:56 -04:00
if Settings . smokeTest
do runSmokeTest = ->
logger . log ( " running smoke tests " )
smokeTest . run ( require . resolve ( __dirname + " /test/smoke/js/SmokeTests.js " ) ) ( { } , resCacher )
setTimeout ( runSmokeTest , 20 * 1000 )
2014-06-05 10:51:24 -04:00
app . get " /health_check " , (req, res)->
2014-06-05 11:13:06 -04:00
res . contentType ( resCacher ? . setContentType )
res . send resCacher ? . code , resCacher ? . body
2014-02-12 12:27:43 -05:00
app . use (error, req, res, next) ->
logger . error err: error , " server error "
2014-11-27 11:19:01 -05:00
res . send error ? . statusCode || 500
2014-02-12 12:27:43 -05:00
app . listen port = ( Settings . internal ? . clsi ? . port or 3013 ) , host = ( Settings . internal ? . clsi ? . host or " localhost " ) , (error) ->
logger . log " CLSI listening on #{ host } : #{ port } "
setInterval () ->
ProjectPersistenceManager . clearExpiredProjects ( )
, tenMinutes = 10 * 60 * 1000