aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-02-16 16:25:53 +0100
committerChocobozzz <chocobozzz@cpy.re>2021-02-18 13:38:09 +0100
commit90a8bd305de4153ec21137a73ff482dcc2e3e19b (patch)
tree2e35b5504ec11bc51579c92a70c77ed3d5ace816 /server/controllers
parent684cdacbbd775b5f404dd7b373e02dd21baf5ff0 (diff)
downloadPeerTube-90a8bd305de4153ec21137a73ff482dcc2e3e19b.tar.gz
PeerTube-90a8bd305de4153ec21137a73ff482dcc2e3e19b.tar.zst
PeerTube-90a8bd305de4153ec21137a73ff482dcc2e3e19b.zip
Dissociate video file names and video uuid
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/api/videos/index.ts7
-rw-r--r--server/controllers/download.ts78
-rw-r--r--server/controllers/index.ts1
-rw-r--r--server/controllers/lazy-static.ts23
-rw-r--r--server/controllers/static.ts88
5 files changed, 105 insertions, 92 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 9504c40a4..dcd6194ae 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -7,7 +7,7 @@ import { changeVideoChannelShare } from '@server/lib/activitypub/share'
7import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url' 7import { getLocalVideoActivityPubUrl } from '@server/lib/activitypub/url'
8import { LiveManager } from '@server/lib/live-manager' 8import { LiveManager } from '@server/lib/live-manager'
9import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' 9import { addOptimizeOrMergeAudioJob, buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
10import { getVideoFilePath } from '@server/lib/video-paths' 10import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
11import { getServerActor } from '@server/models/application/application' 11import { getServerActor } from '@server/models/application/application'
12import { MVideoFullLight } from '@server/types/models' 12import { MVideoFullLight } from '@server/types/models'
13import { VideoCreate, VideoState, VideoUpdate } from '../../../../shared' 13import { VideoCreate, VideoState, VideoUpdate } from '../../../../shared'
@@ -189,6 +189,7 @@ async function addVideo (req: express.Request, res: express.Response) {
189 videoData.duration = videoPhysicalFile['duration'] // duration was added by a previous middleware 189 videoData.duration = videoPhysicalFile['duration'] // duration was added by a previous middleware
190 190
191 const video = new VideoModel(videoData) as MVideoFullLight 191 const video = new VideoModel(videoData) as MVideoFullLight
192 video.VideoChannel = res.locals.videoChannel
192 video.url = getLocalVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object 193 video.url = getLocalVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object
193 194
194 const videoFile = new VideoFileModel({ 195 const videoFile = new VideoFileModel({
@@ -205,6 +206,8 @@ async function addVideo (req: express.Request, res: express.Response) {
205 videoFile.resolution = (await getVideoFileResolution(videoPhysicalFile.path)).videoFileResolution 206 videoFile.resolution = (await getVideoFileResolution(videoPhysicalFile.path)).videoFileResolution
206 } 207 }
207 208
209 videoFile.filename = generateVideoFilename(video, false, videoFile.resolution, videoFile.extname)
210
208 // Move physical file 211 // Move physical file
209 const destination = getVideoFilePath(video, videoFile) 212 const destination = getVideoFilePath(video, videoFile)
210 await move(videoPhysicalFile.path, destination) 213 await move(videoPhysicalFile.path, destination)
@@ -219,7 +222,7 @@ async function addVideo (req: express.Request, res: express.Response) {
219 }) 222 })
220 223
221 // Create the torrent file 224 // Create the torrent file
222 await createTorrentAndSetInfoHash(video, videoFile) 225 await createTorrentAndSetInfoHash(video, video, videoFile)
223 226
224 const { videoCreated } = await sequelizeTypescript.transaction(async t => { 227 const { videoCreated } = await sequelizeTypescript.transaction(async t => {
225 const sequelizeOptions = { transaction: t } 228 const sequelizeOptions = { transaction: t }
diff --git a/server/controllers/download.ts b/server/controllers/download.ts
new file mode 100644
index 000000000..27caa1518
--- /dev/null
+++ b/server/controllers/download.ts
@@ -0,0 +1,78 @@
1import * as cors from 'cors'
2import * as express from 'express'
3import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
4import { getVideoFilePath } from '@server/lib/video-paths'
5import { MVideoFile, MVideoFullLight } from '@server/types/models'
6import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
7import { VideoStreamingPlaylistType } from '@shared/models'
8import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
9import { asyncMiddleware, videosDownloadValidator } from '../middlewares'
10
11const downloadRouter = express.Router()
12
13downloadRouter.use(cors())
14
15downloadRouter.use(
16 STATIC_DOWNLOAD_PATHS.TORRENTS + ':filename',
17 downloadTorrent
18)
19
20downloadRouter.use(
21 STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension',
22 asyncMiddleware(videosDownloadValidator),
23 downloadVideoFile
24)
25
26downloadRouter.use(
27 STATIC_DOWNLOAD_PATHS.HLS_VIDEOS + ':id-:resolution([0-9]+)-fragmented.:extension',
28 asyncMiddleware(videosDownloadValidator),
29 downloadHLSVideoFile
30)
31
32// ---------------------------------------------------------------------------
33
34export {
35 downloadRouter
36}
37
38// ---------------------------------------------------------------------------
39
40async function downloadTorrent (req: express.Request, res: express.Response) {
41 const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename)
42 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
43
44 return res.download(result.path, result.downloadName)
45}
46
47function downloadVideoFile (req: express.Request, res: express.Response) {
48 const video = res.locals.videoAll
49
50 const videoFile = getVideoFile(req, video.VideoFiles)
51 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
52
53 return res.download(getVideoFilePath(video, videoFile), `${video.name}-${videoFile.resolution}p${videoFile.extname}`)
54}
55
56function downloadHLSVideoFile (req: express.Request, res: express.Response) {
57 const video = res.locals.videoAll
58 const playlist = getHLSPlaylist(video)
59 if (!playlist) return res.status(HttpStatusCode.NOT_FOUND_404).end
60
61 const videoFile = getVideoFile(req, playlist.VideoFiles)
62 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
63
64 const filename = `${video.name}-${videoFile.resolution}p-${playlist.getStringType()}${videoFile.extname}`
65 return res.download(getVideoFilePath(playlist, videoFile), filename)
66}
67
68function getVideoFile (req: express.Request, files: MVideoFile[]) {
69 const resolution = parseInt(req.params.resolution, 10)
70 return files.find(f => f.resolution === resolution)
71}
72
73function getHLSPlaylist (video: MVideoFullLight) {
74 const playlist = video.VideoStreamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
75 if (!playlist) return undefined
76
77 return Object.assign(playlist, { Video: video })
78}
diff --git a/server/controllers/index.ts b/server/controllers/index.ts
index 5a199ae9c..fa27ecec2 100644
--- a/server/controllers/index.ts
+++ b/server/controllers/index.ts
@@ -1,6 +1,7 @@
1export * from './activitypub' 1export * from './activitypub'
2export * from './api' 2export * from './api'
3export * from './client' 3export * from './client'
4export * from './download'
4export * from './feeds' 5export * from './feeds'
5export * from './services' 6export * from './services'
6export * from './static' 7export * from './static'
diff --git a/server/controllers/lazy-static.ts b/server/controllers/lazy-static.ts
index 656dea223..c2f5c7b56 100644
--- a/server/controllers/lazy-static.ts
+++ b/server/controllers/lazy-static.ts
@@ -1,12 +1,13 @@
1import * as cors from 'cors' 1import * as cors from 'cors'
2import * as express from 'express' 2import * as express from 'express'
3import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
4import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
5import { logger } from '../helpers/logger'
3import { LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' 6import { LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants'
7import { avatarPathUnsafeCache, pushAvatarProcessInQueue } from '../lib/avatar'
4import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache' 8import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache'
5import { asyncMiddleware } from '../middlewares' 9import { asyncMiddleware } from '../middlewares'
6import { AvatarModel } from '../models/avatar/avatar' 10import { AvatarModel } from '../models/avatar/avatar'
7import { logger } from '../helpers/logger'
8import { avatarPathUnsafeCache, pushAvatarProcessInQueue } from '../lib/avatar'
9import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
10 11
11const lazyStaticRouter = express.Router() 12const lazyStaticRouter = express.Router()
12 13
@@ -27,6 +28,11 @@ lazyStaticRouter.use(
27 asyncMiddleware(getVideoCaption) 28 asyncMiddleware(getVideoCaption)
28) 29)
29 30
31lazyStaticRouter.use(
32 LAZY_STATIC_PATHS.TORRENTS + ':filename',
33 asyncMiddleware(getTorrent)
34)
35
30// --------------------------------------------------------------------------- 36// ---------------------------------------------------------------------------
31 37
32export { 38export {
@@ -67,19 +73,26 @@ async function getAvatar (req: express.Request, res: express.Response) {
67 const path = avatar.getPath() 73 const path = avatar.getPath()
68 74
69 avatarPathUnsafeCache.set(filename, path) 75 avatarPathUnsafeCache.set(filename, path)
70 return res.sendFile(path, { maxAge: STATIC_MAX_AGE.SERVER }) 76 return res.sendFile(path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER })
71} 77}
72 78
73async function getPreview (req: express.Request, res: express.Response) { 79async function getPreview (req: express.Request, res: express.Response) {
74 const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename) 80 const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename)
75 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) 81 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
76 82
77 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.SERVER }) 83 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER })
78} 84}
79 85
80async function getVideoCaption (req: express.Request, res: express.Response) { 86async function getVideoCaption (req: express.Request, res: express.Response) {
81 const result = await VideosCaptionCache.Instance.getFilePath(req.params.filename) 87 const result = await VideosCaptionCache.Instance.getFilePath(req.params.filename)
82 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) 88 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
83 89
90 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER })
91}
92
93async function getTorrent (req: express.Request, res: express.Response) {
94 const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename)
95 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
96
84 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.SERVER }) 97 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.SERVER })
85} 98}
diff --git a/server/controllers/static.ts b/server/controllers/static.ts
index 2064857eb..7cc7f2c62 100644
--- a/server/controllers/static.ts
+++ b/server/controllers/static.ts
@@ -3,10 +3,7 @@ import * as express from 'express'
3import { join } from 'path' 3import { join } from 'path'
4import { getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config' 4import { getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config'
5import { serveIndexHTML } from '@server/lib/client-html' 5import { serveIndexHTML } from '@server/lib/client-html'
6import { getTorrentFilePath, getVideoFilePath } from '@server/lib/video-paths'
7import { MVideoFile, MVideoFullLight } from '@server/types/models'
8import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' 6import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
9import { VideoStreamingPlaylistType } from '@shared/models/videos/video-streaming-playlist.type'
10import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo' 7import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo'
11import { root } from '../helpers/core-utils' 8import { root } from '../helpers/core-utils'
12import { CONFIG, isEmailEnabled } from '../initializers/config' 9import { CONFIG, isEmailEnabled } from '../initializers/config'
@@ -16,14 +13,13 @@ import {
16 HLS_STREAMING_PLAYLIST_DIRECTORY, 13 HLS_STREAMING_PLAYLIST_DIRECTORY,
17 PEERTUBE_VERSION, 14 PEERTUBE_VERSION,
18 ROUTE_CACHE_LIFETIME, 15 ROUTE_CACHE_LIFETIME,
19 STATIC_DOWNLOAD_PATHS,
20 STATIC_MAX_AGE, 16 STATIC_MAX_AGE,
21 STATIC_PATHS, 17 STATIC_PATHS,
22 WEBSERVER 18 WEBSERVER
23} from '../initializers/constants' 19} from '../initializers/constants'
24import { getThemeOrDefault } from '../lib/plugins/theme-utils' 20import { getThemeOrDefault } from '../lib/plugins/theme-utils'
25import { getEnabledResolutions } from '../lib/video-transcoding' 21import { getEnabledResolutions } from '../lib/video-transcoding'
26import { asyncMiddleware, videosDownloadValidator } from '../middlewares' 22import { asyncMiddleware } from '../middlewares'
27import { cacheRoute } from '../middlewares/cache' 23import { cacheRoute } from '../middlewares/cache'
28import { UserModel } from '../models/account/user' 24import { UserModel } from '../models/account/user'
29import { VideoModel } from '../models/video/video' 25import { VideoModel } from '../models/video/video'
@@ -37,47 +33,23 @@ staticRouter.use(cors())
37 Cors is very important to let other servers access torrent and video files 33 Cors is very important to let other servers access torrent and video files
38*/ 34*/
39 35
36// FIXME: deprecated in 3.2, use lazy-statics instead
40const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR 37const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR
41staticRouter.use( 38staticRouter.use(
42 STATIC_PATHS.TORRENTS, 39 STATIC_PATHS.TORRENTS,
43 cors(),
44 express.static(torrentsPhysicalPath, { maxAge: 0 }) // Don't cache because we could regenerate the torrent file 40 express.static(torrentsPhysicalPath, { maxAge: 0 }) // Don't cache because we could regenerate the torrent file
45) 41)
46staticRouter.use(
47 STATIC_DOWNLOAD_PATHS.TORRENTS + ':id-:resolution([0-9]+).torrent',
48 asyncMiddleware(videosDownloadValidator),
49 downloadTorrent
50)
51staticRouter.use(
52 STATIC_DOWNLOAD_PATHS.TORRENTS + ':id-:resolution([0-9]+)-hls.torrent',
53 asyncMiddleware(videosDownloadValidator),
54 downloadHLSVideoFileTorrent
55)
56 42
57// Videos path for webseeding 43// Videos path for webseed
58staticRouter.use( 44staticRouter.use(
59 STATIC_PATHS.WEBSEED, 45 STATIC_PATHS.WEBSEED,
60 cors(),
61 express.static(CONFIG.STORAGE.VIDEOS_DIR, { fallthrough: false }) // 404 because we don't have this video 46 express.static(CONFIG.STORAGE.VIDEOS_DIR, { fallthrough: false }) // 404 because we don't have this video
62) 47)
63staticRouter.use( 48staticRouter.use(
64 STATIC_PATHS.REDUNDANCY, 49 STATIC_PATHS.REDUNDANCY,
65 cors(),
66 express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404 because we don't have this video 50 express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404 because we don't have this video
67) 51)
68 52
69staticRouter.use(
70 STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension',
71 asyncMiddleware(videosDownloadValidator),
72 downloadVideoFile
73)
74
75staticRouter.use(
76 STATIC_DOWNLOAD_PATHS.HLS_VIDEOS + ':id-:resolution([0-9]+)-fragmented.:extension',
77 asyncMiddleware(videosDownloadValidator),
78 downloadHLSVideoFile
79)
80
81// HLS 53// HLS
82staticRouter.use( 54staticRouter.use(
83 STATIC_PATHS.STREAMING_PLAYLISTS.HLS, 55 STATIC_PATHS.STREAMING_PLAYLISTS.HLS,
@@ -327,60 +299,6 @@ async function generateNodeinfo (req: express.Request, res: express.Response) {
327 return res.send(json).end() 299 return res.send(json).end()
328} 300}
329 301
330function downloadTorrent (req: express.Request, res: express.Response) {
331 const video = res.locals.videoAll
332
333 const videoFile = getVideoFile(req, video.VideoFiles)
334 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
335
336 return res.download(getTorrentFilePath(video, videoFile), `${video.name}-${videoFile.resolution}p.torrent`)
337}
338
339function downloadHLSVideoFileTorrent (req: express.Request, res: express.Response) {
340 const video = res.locals.videoAll
341
342 const playlist = getHLSPlaylist(video)
343 if (!playlist) return res.status(HttpStatusCode.NOT_FOUND_404).end
344
345 const videoFile = getVideoFile(req, playlist.VideoFiles)
346 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
347
348 return res.download(getTorrentFilePath(playlist, videoFile), `${video.name}-${videoFile.resolution}p-hls.torrent`)
349}
350
351function downloadVideoFile (req: express.Request, res: express.Response) {
352 const video = res.locals.videoAll
353
354 const videoFile = getVideoFile(req, video.VideoFiles)
355 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
356
357 return res.download(getVideoFilePath(video, videoFile), `${video.name}-${videoFile.resolution}p${videoFile.extname}`)
358}
359
360function downloadHLSVideoFile (req: express.Request, res: express.Response) {
361 const video = res.locals.videoAll
362 const playlist = getHLSPlaylist(video)
363 if (!playlist) return res.status(HttpStatusCode.NOT_FOUND_404).end
364
365 const videoFile = getVideoFile(req, playlist.VideoFiles)
366 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
367
368 const filename = `${video.name}-${videoFile.resolution}p-${playlist.getStringType()}${videoFile.extname}`
369 return res.download(getVideoFilePath(playlist, videoFile), filename)
370}
371
372function getVideoFile (req: express.Request, files: MVideoFile[]) {
373 const resolution = parseInt(req.params.resolution, 10)
374 return files.find(f => f.resolution === resolution)
375}
376
377function getHLSPlaylist (video: MVideoFullLight) {
378 const playlist = video.VideoStreamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
379 if (!playlist) return undefined
380
381 return Object.assign(playlist, { Video: video })
382}
383
384function getCup (req: express.Request, res: express.Response, next: express.NextFunction) { 302function getCup (req: express.Request, res: express.Response, next: express.NextFunction) {
385 res.status(HttpStatusCode.I_AM_A_TEAPOT_418) 303 res.status(HttpStatusCode.I_AM_A_TEAPOT_418)
386 res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1') 304 res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1')