| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- 'use strict'
- /* eslint-disable no-console */
- // Metrics must be initialized before importing anything else
- require('@overleaf/metrics/initialize')
- const config = require('config')
- const Events = require('node:events')
- const express = require('express')
- const helmet = require('helmet')
- const HTTPStatus = require('http-status')
- const logger = require('@overleaf/logger')
- const Metrics = require('@overleaf/metrics')
- const bodyParser = require('body-parser')
- const security = require('./api/middleware/security')
- const healthChecks = require('./api/controllers/health_checks')
- const { mongodb, loadGlobalBlobs } = require('./storage')
- const projectsRoutes = require('./api/routes/projects')
- const projectImportRoutes = require('./api/routes/project_import')
- const { createHandleValidationError } = require('@overleaf/validation-tools')
- Events.setMaxListeners(20)
- const app = express()
- module.exports = app
- const handleValidationError = createHandleValidationError(
- HTTPStatus.UNPROCESSABLE_ENTITY
- )
- logger.initialize('history-v1')
- Metrics.open_sockets.monitor()
- Metrics.injectMetricsRoute(app)
- app.use(Metrics.http.monitor(logger))
- Metrics.leaked_sockets.monitor(logger)
- // We may have fairly large JSON bodies when receiving large Changes. Clients
- // may have to handle 413 status codes and try creating files instead of sending
- // text content in changes.
- app.use(bodyParser.json({ limit: '12MB' }))
- app.use(
- bodyParser.urlencoded({
- extended: false,
- })
- )
- security.setupSSL(app)
- security.setupBasicHttpAuthForSwaggerDocs(app)
- const HTTP_REQUEST_TIMEOUT = parseInt(config.get('httpRequestTimeout'), 10)
- app.use(function (req, res, next) {
- res.setTimeout(HTTP_REQUEST_TIMEOUT)
- next()
- })
- app.get('/', function (req, res) {
- res.send('')
- })
- app.get('/status', healthChecks.status)
- app.get('/health_check', healthChecks.healthCheck)
- app.get('/docs', function (req, res) {
- res.send('OK')
- })
- function setupErrorHandling() {
- app.use(function (req, res, next) {
- const err = new Error('Not Found')
- err.status = HTTPStatus.NOT_FOUND
- return next(err)
- })
- app.use(handleValidationError)
- app.use(function (err, req, res, next) {
- const projectId = req.params?.project_id || req.body?.projectId
- logger.error({ err, projectId }, err.message)
- if (res.headersSent) {
- return next(err)
- }
- // Handle errors that specify a statusCode. Some come from our code. Some
- // bubble up from AWS SDK, but they sometimes have the statusCode set to
- // 200, notably some InternalErrors and TimeoutErrors, so we have to guard
- // against that. We also check `status`, but `statusCode` is preferred.
- const statusCode = err.statusCode || err.status
- if (err.headers) {
- res.set(err.headers)
- }
- if (statusCode && statusCode >= 400 && statusCode < 600) {
- res.status(statusCode)
- } else {
- res.status(HTTPStatus.INTERNAL_SERVER_ERROR)
- }
- const sendErrorToClient = app.get('env') === 'development'
- res.json({
- message: err.message,
- error: sendErrorToClient ? err : {},
- })
- })
- }
- app.setup = async function appSetup() {
- await mongodb.client.connect()
- logger.info('Connected to MongoDB')
- await loadGlobalBlobs()
- logger.info('Global blobs loaded')
- app.use(helmet())
- app.use('/api', projectsRoutes)
- app.use('/api', projectImportRoutes)
- setupErrorHandling()
- }
- async function startApp() {
- await app.setup()
- const port = parseInt(process.env.PORT, 10) || 3100
- app.listen(port, err => {
- if (err) {
- console.error(err)
- process.exit(1)
- }
- Metrics.event_loop.monitor(logger)
- Metrics.memory.monitor(logger)
- })
- }
- // Run this if we're called directly
- if (!module.parent) {
- startApp().catch(err => {
- console.error(err)
- process.exit(1)
- })
- }
|