aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/client-html.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/client-html.ts')
-rw-r--r--server/lib/client-html.ts48
1 files changed, 39 insertions, 9 deletions
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index 203bd3893..72194416d 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -2,12 +2,14 @@ import * as express from 'express'
2import { readFile } from 'fs-extra' 2import { readFile } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import validator from 'validator' 4import validator from 'validator'
5import { escapeHTML } from '@shared/core-utils/renderer'
6import { HTMLServerConfig } from '@shared/models'
5import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' 7import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
6import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' 8import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
7import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' 9import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
8import { isTestInstance, sha256 } from '../helpers/core-utils' 10import { isTestInstance, sha256 } from '../helpers/core-utils'
9import { escapeHTML } from '@shared/core-utils/renderer'
10import { logger } from '../helpers/logger' 11import { logger } from '../helpers/logger'
12import { mdToPlainText } from '../helpers/markdown'
11import { CONFIG } from '../initializers/config' 13import { CONFIG } from '../initializers/config'
12import { 14import {
13 ACCEPT_HEADERS, 15 ACCEPT_HEADERS,
@@ -19,12 +21,13 @@ import {
19 WEBSERVER 21 WEBSERVER
20} from '../initializers/constants' 22} from '../initializers/constants'
21import { AccountModel } from '../models/account/account' 23import { AccountModel } from '../models/account/account'
24import { getActivityStreamDuration } from '../models/video/formatter/video-format-utils'
22import { VideoModel } from '../models/video/video' 25import { VideoModel } from '../models/video/video'
23import { VideoChannelModel } from '../models/video/video-channel' 26import { VideoChannelModel } from '../models/video/video-channel'
24import { getActivityStreamDuration } from '../models/video/video-format-utils'
25import { VideoPlaylistModel } from '../models/video/video-playlist' 27import { VideoPlaylistModel } from '../models/video/video-playlist'
26import { MAccountActor, MChannelActor } from '../types/models' 28import { MAccountActor, MChannelActor } from '../types/models'
27import { mdToPlainText } from '../helpers/markdown' 29import { ServerConfigManager } from './server-config-manager'
30import { toCompleteUUID } from '@server/helpers/custom-validators/misc'
28 31
29type Tags = { 32type Tags = {
30 ogType: string 33 ogType: string
@@ -76,7 +79,9 @@ class ClientHtml {
76 return customHtml 79 return customHtml
77 } 80 }
78 81
79 static async getWatchHTMLPage (videoId: string, req: express.Request, res: express.Response) { 82 static async getWatchHTMLPage (videoIdArg: string, req: express.Request, res: express.Response) {
83 const videoId = toCompleteUUID(videoIdArg)
84
80 // Let Angular application handle errors 85 // Let Angular application handle errors
81 if (!validator.isInt(videoId) && !validator.isUUID(videoId, 4)) { 86 if (!validator.isInt(videoId) && !validator.isUUID(videoId, 4)) {
82 res.status(HttpStatusCode.NOT_FOUND_404) 87 res.status(HttpStatusCode.NOT_FOUND_404)
@@ -134,7 +139,9 @@ class ClientHtml {
134 return customHtml 139 return customHtml
135 } 140 }
136 141
137 static async getWatchPlaylistHTMLPage (videoPlaylistId: string, req: express.Request, res: express.Response) { 142 static async getWatchPlaylistHTMLPage (videoPlaylistIdArg: string, req: express.Request, res: express.Response) {
143 const videoPlaylistId = toCompleteUUID(videoPlaylistIdArg)
144
138 // Let Angular application handle errors 145 // Let Angular application handle errors
139 if (!validator.isInt(videoPlaylistId) && !validator.isUUID(videoPlaylistId, 4)) { 146 if (!validator.isInt(videoPlaylistId) && !validator.isUUID(videoPlaylistId, 4)) {
140 res.status(HttpStatusCode.NOT_FOUND_404) 147 res.status(HttpStatusCode.NOT_FOUND_404)
@@ -196,11 +203,22 @@ class ClientHtml {
196 } 203 }
197 204
198 static async getAccountHTMLPage (nameWithHost: string, req: express.Request, res: express.Response) { 205 static async getAccountHTMLPage (nameWithHost: string, req: express.Request, res: express.Response) {
199 return this.getAccountOrChannelHTMLPage(() => AccountModel.loadByNameWithHost(nameWithHost), req, res) 206 const accountModelPromise = AccountModel.loadByNameWithHost(nameWithHost)
207 return this.getAccountOrChannelHTMLPage(() => accountModelPromise, req, res)
200 } 208 }
201 209
202 static async getVideoChannelHTMLPage (nameWithHost: string, req: express.Request, res: express.Response) { 210 static async getVideoChannelHTMLPage (nameWithHost: string, req: express.Request, res: express.Response) {
203 return this.getAccountOrChannelHTMLPage(() => VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithHost), req, res) 211 const videoChannelModelPromise = VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithHost)
212 return this.getAccountOrChannelHTMLPage(() => videoChannelModelPromise, req, res)
213 }
214
215 static async getActorHTMLPage (nameWithHost: string, req: express.Request, res: express.Response) {
216 const [ account, channel ] = await Promise.all([
217 AccountModel.loadByNameWithHost(nameWithHost),
218 VideoChannelModel.loadByNameWithHostAndPopulateAccount(nameWithHost)
219 ])
220
221 return this.getAccountOrChannelHTMLPage(() => Promise.resolve(account || channel), req, res)
204 } 222 }
205 223
206 static async getEmbedHTML () { 224 static async getEmbedHTML () {
@@ -209,11 +227,14 @@ class ClientHtml {
209 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] 227 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
210 228
211 const buffer = await readFile(path) 229 const buffer = await readFile(path)
230 const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig()
212 231
213 let html = buffer.toString() 232 let html = buffer.toString()
214 html = await ClientHtml.addAsyncPluginCSS(html) 233 html = await ClientHtml.addAsyncPluginCSS(html)
215 html = ClientHtml.addCustomCSS(html) 234 html = ClientHtml.addCustomCSS(html)
216 html = ClientHtml.addTitleTag(html) 235 html = ClientHtml.addTitleTag(html)
236 html = ClientHtml.addDescriptionTag(html)
237 html = ClientHtml.addServerConfig(html, serverConfig)
217 238
218 ClientHtml.htmlCache[path] = html 239 ClientHtml.htmlCache[path] = html
219 240
@@ -275,6 +296,7 @@ class ClientHtml {
275 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] 296 if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
276 297
277 const buffer = await readFile(path) 298 const buffer = await readFile(path)
299 const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig()
278 300
279 let html = buffer.toString() 301 let html = buffer.toString()
280 302
@@ -283,6 +305,7 @@ class ClientHtml {
283 html = ClientHtml.addFaviconContentHash(html) 305 html = ClientHtml.addFaviconContentHash(html)
284 html = ClientHtml.addLogoContentHash(html) 306 html = ClientHtml.addLogoContentHash(html)
285 html = ClientHtml.addCustomCSS(html) 307 html = ClientHtml.addCustomCSS(html)
308 html = ClientHtml.addServerConfig(html, serverConfig)
286 html = await ClientHtml.addAsyncPluginCSS(html) 309 html = await ClientHtml.addAsyncPluginCSS(html)
287 310
288 ClientHtml.htmlCache[path] = html 311 ClientHtml.htmlCache[path] = html
@@ -355,6 +378,13 @@ class ClientHtml {
355 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag) 378 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag)
356 } 379 }
357 380
381 private static addServerConfig (htmlStringPage: string, serverConfig: HTMLServerConfig) {
382 const serverConfigString = JSON.stringify(serverConfig)
383 const configScriptTag = `<script type="application/javascript">window.PeerTubeServerConfig = '${serverConfigString}'</script>`
384
385 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.SERVER_CONFIG, configScriptTag)
386 }
387
358 private static async addAsyncPluginCSS (htmlStringPage: string) { 388 private static async addAsyncPluginCSS (htmlStringPage: string) {
359 const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH) 389 const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH)
360 if (globalCSSContent.byteLength === 0) return htmlStringPage 390 if (globalCSSContent.byteLength === 0) return htmlStringPage
@@ -524,11 +554,11 @@ async function serveIndexHTML (req: express.Request, res: express.Response) {
524 return 554 return
525 } catch (err) { 555 } catch (err) {
526 logger.error('Cannot generate HTML page.', err) 556 logger.error('Cannot generate HTML page.', err)
527 return res.sendStatus(HttpStatusCode.INTERNAL_SERVER_ERROR_500) 557 return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500).end()
528 } 558 }
529 } 559 }
530 560
531 return res.sendStatus(HttpStatusCode.NOT_ACCEPTABLE_406) 561 return res.status(HttpStatusCode.NOT_ACCEPTABLE_406).end()
532} 562}
533 563
534// --------------------------------------------------------------------------- 564// ---------------------------------------------------------------------------