import { isTestInstance } from './server/helpers/core-utils' if (isTestInstance()) { require('source-map-support').install() } import * as bodyParser from 'body-parser' import * as express from 'express' import * as cors from 'cors' import * as morgan from 'morgan' import { apiRouter } from './server/controllers/api' import { logger } from './server/helpers/logger' import { API_VERSION, CONFIG, getWebserverUrl } from './server/initializers/constants' import { VideosIndexer } from './server/lib/schedulers/videos-indexer' import { initVideosIndex } from './server/lib/elastic-search-videos' import { initChannelsIndex } from './server/lib/elastic-search-channels' import { join } from 'path' import { readFile } from 'fs-extra' const app = express() const url = getWebserverUrl() app.use(morgan('combined', { stream: { write: logger.info.bind(logger) } })) app.use(bodyParser.json({ type: [ 'application/json', 'application/*+json' ], limit: '5mb' })) app.use(bodyParser.urlencoded({ extended: false })) // ----------- Views, routes and static files ----------- app.use(cors()) const apiRoute = '/api/' + API_VERSION app.use(apiRoute, apiRouter) // Static client files app.use('/js/', express.static(join(__dirname, '../client/dist/js'))) app.use('/css/', express.static(join(__dirname, '../client/dist/css'))) app.use('/img/', express.static(join(__dirname, '../client/dist/img'))) app.use('/theme/', express.static(join(__dirname, './themes'))) app.use('/opensearch.xml', async function (req, res) { const data = ` ${CONFIG.SEARCH_INSTANCE.NAME} ${CONFIG.SEARCH_INSTANCE.DESCRIPTION} ${url}/img/favicon.png * peertube video open true UTF-8 UTF-8 Framasoft: contact.framasoft.org ` return res.type('application/xml').send(data).end() }) let indexHTML: string app.use('/*', async function (req, res) { res.set('Content-Type', 'text/html; charset=UTF-8') if (indexHTML) return res.send(indexHTML) let bufferCSS: Buffer if (CONFIG.SEARCH_INSTANCE.THEME !== 'default') { try { bufferCSS = await readFile(join(__dirname, 'themes', CONFIG.SEARCH_INSTANCE.THEME, 'index.css')) } catch (err) { logger.error({ err }, 'Cannot fetch CSS theme.') } } const title = CONFIG.SEARCH_INSTANCE.NAME const description = CONFIG.SEARCH_INSTANCE.DESCRIPTION const styleCSS = bufferCSS ? `` : '' const tags = ` ${title} ${styleCSS}` const buffer = await readFile(join(__dirname, '../client/dist/index.html')) indexHTML = buffer.toString() indexHTML = indexHTML.replace('', tags + '') return res.send(indexHTML) }) // ----------- Errors ----------- // Catch 404 and forward to error handler app.use(function (req, res, next) { const err = new Error('Not Found') as any err.status = 404 next(err) }) app.use(function (err, req, res, next) { let error = 'Unknown error.' if (err) { error = err.stack || err.message || err } logger.error({ error }, 'Error in controller.') return res.status(err.status || 500).end() }) // ----------- Run ----------- app.listen(CONFIG.LISTEN.PORT, async () => { logger.info('Server listening on port %d', CONFIG.LISTEN.PORT) try { await Promise.all([ initVideosIndex(), initChannelsIndex() ]) } catch (err) { logger.error('Cannot init videos index.', { err }) process.exit(-1) } VideosIndexer.Instance.enable() VideosIndexer.Instance.execute() .catch(err => logger.error('Cannot run video indexer', { err })) })