client.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import * as express from 'express'
  2. import { join } from 'path'
  3. import { root } from '../helpers/core-utils'
  4. import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants'
  5. import { asyncMiddleware, embedCSP } from '../middlewares'
  6. import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n'
  7. import { ClientHtml } from '../lib/client-html'
  8. import { logger } from '../helpers/logger'
  9. const clientsRouter = express.Router()
  10. const distPath = join(root(), 'client', 'dist')
  11. const assetsImagesPath = join(root(), 'client', 'dist', 'assets', 'images')
  12. const embedPath = join(distPath, 'standalone', 'videos', 'embed.html')
  13. const testEmbedPath = join(distPath, 'standalone', 'videos', 'test-embed.html')
  14. // Special route that add OpenGraph and oEmbed tags
  15. // Do not use a template engine for a so little thing
  16. clientsRouter.use('/videos/watch/:id', asyncMiddleware(generateWatchHtmlPage))
  17. clientsRouter.use('/accounts/:nameWithHost', asyncMiddleware(generateAccountHtmlPage))
  18. clientsRouter.use('/video-channels/:nameWithHost', asyncMiddleware(generateVideoChannelHtmlPage))
  19. clientsRouter.use(
  20. '/videos/embed',
  21. embedCSP,
  22. (req: express.Request, res: express.Response) => {
  23. res.removeHeader('X-Frame-Options')
  24. res.sendFile(embedPath)
  25. }
  26. )
  27. clientsRouter.use(
  28. '/videos/test-embed',
  29. (req: express.Request, res: express.Response) => res.sendFile(testEmbedPath)
  30. )
  31. // Static HTML/CSS/JS client files
  32. const staticClientFiles = [
  33. 'manifest.webmanifest',
  34. 'ngsw-worker.js',
  35. 'ngsw.json'
  36. ]
  37. for (const staticClientFile of staticClientFiles) {
  38. const path = join(root(), 'client', 'dist', staticClientFile)
  39. clientsRouter.use('/' + staticClientFile, express.static(path, { maxAge: STATIC_MAX_AGE }))
  40. }
  41. clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE }))
  42. clientsRouter.use('/client/assets/images', express.static(assetsImagesPath, { maxAge: STATIC_MAX_AGE }))
  43. clientsRouter.use('/client/locales/:locale/:file.json', function (req, res) {
  44. const locale = req.params.locale
  45. const file = req.params.file
  46. if (is18nLocale(locale) && LOCALE_FILES.indexOf(file) !== -1) {
  47. const completeLocale = getCompleteLocale(locale)
  48. const completeFileLocale = buildFileLocale(completeLocale)
  49. return res.sendFile(join(__dirname, `../../../client/dist/locale/${file}_${completeFileLocale}.json`))
  50. }
  51. return res.sendStatus(404)
  52. })
  53. // 404 for static files not found
  54. clientsRouter.use('/client/*', (req: express.Request, res: express.Response, next: express.NextFunction) => {
  55. res.sendStatus(404)
  56. })
  57. // Always serve index client page (the client is a single page application, let it handle routing)
  58. // Try to provide the right language index.html
  59. clientsRouter.use('/(:language)?', async function (req, res) {
  60. if (req.accepts(ACCEPT_HEADERS) === 'html') {
  61. try {
  62. await generateHTMLPage(req, res, req.params.language)
  63. return
  64. } catch (err) {
  65. logger.error('Cannot generate HTML page.', err)
  66. }
  67. }
  68. return res.status(404).end()
  69. })
  70. // ---------------------------------------------------------------------------
  71. export {
  72. clientsRouter
  73. }
  74. // ---------------------------------------------------------------------------
  75. async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
  76. const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
  77. return sendHTML(html, res)
  78. }
  79. async function generateWatchHtmlPage (req: express.Request, res: express.Response) {
  80. const html = await ClientHtml.getWatchHTMLPage(req.params.id + '', req, res)
  81. return sendHTML(html, res)
  82. }
  83. async function generateAccountHtmlPage (req: express.Request, res: express.Response) {
  84. const html = await ClientHtml.getAccountHTMLPage(req.params.nameWithHost, req, res)
  85. return sendHTML(html, res)
  86. }
  87. async function generateVideoChannelHtmlPage (req: express.Request, res: express.Response) {
  88. const html = await ClientHtml.getVideoChannelHTMLPage(req.params.nameWithHost, req, res)
  89. return sendHTML(html, res)
  90. }
  91. function sendHTML (html: string, res: express.Response) {
  92. res.set('Content-Type', 'text/html; charset=UTF-8')
  93. return res.send(html)
  94. }