server.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { isTestInstance } from './server/helpers/core-utils'
  2. if (isTestInstance()) {
  3. require('source-map-support').install()
  4. }
  5. // ----------- Node modules -----------
  6. import * as bodyParser from 'body-parser'
  7. import * as express from 'express'
  8. import * as http from 'http'
  9. import * as morgan from 'morgan'
  10. import * as path from 'path'
  11. import * as bitTorrentTracker from 'bittorrent-tracker'
  12. import * as cors from 'cors'
  13. import { Server as WebSocketServer } from 'ws'
  14. const TrackerServer = bitTorrentTracker.Server
  15. process.title = 'peertube'
  16. // Create our main app
  17. const app = express()
  18. // ----------- Core checker -----------
  19. import { checkMissedConfig, checkFFmpeg, checkConfig } from './server/initializers/checker'
  20. const missed = checkMissedConfig()
  21. if (missed.length !== 0) {
  22. throw new Error('Your configuration files miss keys: ' + missed)
  23. }
  24. import { API_VERSION, CONFIG, STATIC_PATHS } from './server/initializers/constants'
  25. checkFFmpeg(CONFIG)
  26. const errorMessage = checkConfig()
  27. if (errorMessage !== null) {
  28. throw new Error(errorMessage)
  29. }
  30. // ----------- Database -----------
  31. // Do not use barrels because we don't want to load all modules here (we need to initialize database first)
  32. import { logger } from './server/helpers/logger'
  33. // Initialize database and models
  34. import { database as db } from './server/initializers/database'
  35. db.init(false).then(() => onDatabaseInitDone())
  36. // ----------- PeerTube modules -----------
  37. import { migrate, installApplication } from './server/initializers'
  38. import { activitypubHttpJobScheduler, transcodingJobScheduler, VideosPreviewCache } from './server/lib'
  39. import { apiRouter, clientsRouter, staticRouter, servicesRouter, webfingerRouter, activityPubRouter } from './server/controllers'
  40. // ----------- Command line -----------
  41. // ----------- App -----------
  42. // Enable CORS for develop
  43. if (isTestInstance()) {
  44. app.use((req, res, next) => {
  45. // These routes have already cors
  46. if (
  47. req.path.indexOf(STATIC_PATHS.TORRENTS) === -1 &&
  48. req.path.indexOf(STATIC_PATHS.WEBSEED) === -1
  49. ) {
  50. return (cors({
  51. origin: 'http://localhost:3000',
  52. credentials: true
  53. }))(req, res, next)
  54. }
  55. return next()
  56. })
  57. }
  58. // For the logger
  59. app.use(morgan('combined', {
  60. stream: { write: logger.info }
  61. }))
  62. // For body requests
  63. app.use(bodyParser.json({ limit: '500kb' }))
  64. app.use(bodyParser.urlencoded({ extended: false }))
  65. // ----------- Tracker -----------
  66. const trackerServer = new TrackerServer({
  67. http: false,
  68. udp: false,
  69. ws: false,
  70. dht: false
  71. })
  72. trackerServer.on('error', function (err) {
  73. logger.error(err)
  74. })
  75. trackerServer.on('warning', function (err) {
  76. logger.error(err)
  77. })
  78. const server = http.createServer(app)
  79. const wss = new WebSocketServer({ server: server, path: '/tracker/socket' })
  80. wss.on('connection', function (ws) {
  81. trackerServer.onWebSocketConnection(ws)
  82. })
  83. const onHttpRequest = trackerServer.onHttpRequest.bind(trackerServer)
  84. app.get('/tracker/announce', (req, res) => onHttpRequest(req, res, { action: 'announce' }))
  85. app.get('/tracker/scrape', (req, res) => onHttpRequest(req, res, { action: 'scrape' }))
  86. // ----------- Views, routes and static files -----------
  87. // API
  88. const apiRoute = '/api/' + API_VERSION
  89. app.use(apiRoute, apiRouter)
  90. // Services (oembed...)
  91. app.use('/services', servicesRouter)
  92. app.use('/', webfingerRouter)
  93. app.use('/', activityPubRouter)
  94. // Client files
  95. app.use('/', clientsRouter)
  96. // Static files
  97. app.use('/', staticRouter)
  98. // Always serve index client page (the client is a single page application, let it handle routing)
  99. app.use('/*', function (req, res) {
  100. res.sendFile(path.join(__dirname, '../client/dist/index.html'))
  101. })
  102. // ----------- Errors -----------
  103. // Catch 404 and forward to error handler
  104. app.use(function (req, res, next) {
  105. const err = new Error('Not Found')
  106. err['status'] = 404
  107. next(err)
  108. })
  109. app.use(function (err, req, res, next) {
  110. logger.error(err)
  111. res.sendStatus(err.status || 500)
  112. })
  113. // ----------- Run -----------
  114. function onDatabaseInitDone () {
  115. const port = CONFIG.LISTEN.PORT
  116. // Run the migration scripts if needed
  117. migrate()
  118. .then(() => installApplication())
  119. .then(() => {
  120. // ----------- Make the server listening -----------
  121. server.listen(port, () => {
  122. VideosPreviewCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE)
  123. activitypubHttpJobScheduler.activate()
  124. transcodingJobScheduler.activate()
  125. logger.info('Server listening on port %d', port)
  126. logger.info('Web server: %s', CONFIG.WEBSERVER.URL)
  127. })
  128. })
  129. }