Refractor retry transaction function
[oweals/peertube.git] / server / controllers / static.ts
1 import * as cors from 'cors'
2 import * as express from 'express'
3 import { CONFIG, STATIC_DOWNLOAD_PATHS, STATIC_MAX_AGE, STATIC_PATHS } from '../initializers'
4 import { VideosPreviewCache } from '../lib/cache'
5 import { asyncMiddleware, videosGetValidator } from '../middlewares'
6 import { VideoModel } from '../models/video/video'
7
8 const staticRouter = express.Router()
9
10 /*
11   Cors is very important to let other servers access torrent and video files
12 */
13
14 const torrentsPhysicalPath = CONFIG.STORAGE.TORRENTS_DIR
15 staticRouter.use(
16   STATIC_PATHS.TORRENTS,
17   cors(),
18   express.static(torrentsPhysicalPath, { maxAge: 0 }) // Don't cache because we could regenerate the torrent file
19 )
20 staticRouter.use(
21   STATIC_DOWNLOAD_PATHS.TORRENTS + ':id-:resolution([0-9]+).torrent',
22   asyncMiddleware(videosGetValidator),
23   asyncMiddleware(downloadTorrent)
24 )
25
26 // Videos path for webseeding
27 const videosPhysicalPath = CONFIG.STORAGE.VIDEOS_DIR
28 staticRouter.use(
29   STATIC_PATHS.WEBSEED,
30   cors(),
31   express.static(videosPhysicalPath, { maxAge: STATIC_MAX_AGE })
32 )
33 staticRouter.use(
34   STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension',
35   asyncMiddleware(videosGetValidator),
36   asyncMiddleware(downloadVideoFile)
37 )
38
39 // Thumbnails path for express
40 const thumbnailsPhysicalPath = CONFIG.STORAGE.THUMBNAILS_DIR
41 staticRouter.use(
42   STATIC_PATHS.THUMBNAILS,
43   express.static(thumbnailsPhysicalPath, { maxAge: STATIC_MAX_AGE })
44 )
45
46 const avatarsPhysicalPath = CONFIG.STORAGE.AVATARS_DIR
47 staticRouter.use(
48   STATIC_PATHS.AVATARS,
49   express.static(avatarsPhysicalPath, { maxAge: STATIC_MAX_AGE })
50 )
51
52 // Video previews path for express
53 staticRouter.use(
54   STATIC_PATHS.PREVIEWS + ':uuid.jpg',
55   asyncMiddleware(getPreview)
56 )
57
58 // robots.txt service
59 staticRouter.get('/robots.txt', (req: express.Request, res: express.Response) => {
60   res.type('text/plain')
61   return res.send(CONFIG.INSTANCE.ROBOTS)
62 })
63
64 // ---------------------------------------------------------------------------
65
66 export {
67   staticRouter
68 }
69
70 // ---------------------------------------------------------------------------
71
72 async function getPreview (req: express.Request, res: express.Response, next: express.NextFunction) {
73   const path = await VideosPreviewCache.Instance.getPreviewPath(req.params.uuid)
74   if (!path) return res.sendStatus(404)
75
76   return res.sendFile(path, { maxAge: STATIC_MAX_AGE })
77 }
78
79 async function downloadTorrent (req: express.Request, res: express.Response, next: express.NextFunction) {
80   const { video, videoFile } = getVideoAndFile(req, res)
81   if (!videoFile) return res.status(404).end()
82
83   return res.download(video.getTorrentFilePath(videoFile), `${video.name}-${videoFile.resolution}p.torrent`)
84 }
85
86 async function downloadVideoFile (req: express.Request, res: express.Response, next: express.NextFunction) {
87   const { video, videoFile } = getVideoAndFile(req, res)
88   if (!videoFile) return res.status(404).end()
89
90   return res.download(video.getVideoFilePath(videoFile), `${video.name}-${videoFile.resolution}p${videoFile.extname}`)
91 }
92
93 function getVideoAndFile (req: express.Request, res: express.Response) {
94   const resolution = parseInt(req.params.resolution, 10)
95   const video: VideoModel = res.locals.video
96
97   const videoFile = video.VideoFiles.find(f => f.resolution === resolution)
98
99   return { video, videoFile }
100 }