diff options
Diffstat (limited to 'server/controllers/lazy-static.ts')
-rw-r--r-- | server/controllers/lazy-static.ts | 118 |
1 files changed, 52 insertions, 66 deletions
diff --git a/server/controllers/lazy-static.ts b/server/controllers/lazy-static.ts index b082e41f6..dad30365c 100644 --- a/server/controllers/lazy-static.ts +++ b/server/controllers/lazy-static.ts | |||
@@ -1,14 +1,28 @@ | |||
1 | import cors from 'cors' | 1 | import cors from 'cors' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' | 3 | import { CONFIG } from '@server/initializers/config' |
4 | import { MActorImage } from '@server/types/models' | ||
5 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' | 4 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' |
6 | import { logger } from '../helpers/logger' | 5 | import { FILES_CACHE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' |
7 | import { ACTOR_IMAGES_SIZE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' | 6 | import { |
8 | import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache' | 7 | AvatarPermanentFileCache, |
9 | import { actorImagePathUnsafeCache, downloadActorImageFromWorker } from '../lib/local-actor' | 8 | VideoCaptionsSimpleFileCache, |
9 | VideoMiniaturePermanentFileCache, | ||
10 | VideoPreviewsSimpleFileCache, | ||
11 | VideoStoryboardsSimpleFileCache, | ||
12 | VideoTorrentsSimpleFileCache | ||
13 | } from '../lib/files-cache' | ||
10 | import { asyncMiddleware, handleStaticError } from '../middlewares' | 14 | import { asyncMiddleware, handleStaticError } from '../middlewares' |
11 | import { ActorImageModel } from '../models/actor/actor-image' | 15 | |
16 | // --------------------------------------------------------------------------- | ||
17 | // Cache initializations | ||
18 | // --------------------------------------------------------------------------- | ||
19 | |||
20 | VideoPreviewsSimpleFileCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE, FILES_CACHE.PREVIEWS.MAX_AGE) | ||
21 | VideoCaptionsSimpleFileCache.Instance.init(CONFIG.CACHE.VIDEO_CAPTIONS.SIZE, FILES_CACHE.VIDEO_CAPTIONS.MAX_AGE) | ||
22 | VideoTorrentsSimpleFileCache.Instance.init(CONFIG.CACHE.TORRENTS.SIZE, FILES_CACHE.TORRENTS.MAX_AGE) | ||
23 | VideoStoryboardsSimpleFileCache.Instance.init(CONFIG.CACHE.STORYBOARDS.SIZE, FILES_CACHE.STORYBOARDS.MAX_AGE) | ||
24 | |||
25 | // --------------------------------------------------------------------------- | ||
12 | 26 | ||
13 | const lazyStaticRouter = express.Router() | 27 | const lazyStaticRouter = express.Router() |
14 | 28 | ||
@@ -27,12 +41,24 @@ lazyStaticRouter.use( | |||
27 | ) | 41 | ) |
28 | 42 | ||
29 | lazyStaticRouter.use( | 43 | lazyStaticRouter.use( |
44 | LAZY_STATIC_PATHS.THUMBNAILS + ':filename', | ||
45 | asyncMiddleware(getThumbnail), | ||
46 | handleStaticError | ||
47 | ) | ||
48 | |||
49 | lazyStaticRouter.use( | ||
30 | LAZY_STATIC_PATHS.PREVIEWS + ':filename', | 50 | LAZY_STATIC_PATHS.PREVIEWS + ':filename', |
31 | asyncMiddleware(getPreview), | 51 | asyncMiddleware(getPreview), |
32 | handleStaticError | 52 | handleStaticError |
33 | ) | 53 | ) |
34 | 54 | ||
35 | lazyStaticRouter.use( | 55 | lazyStaticRouter.use( |
56 | LAZY_STATIC_PATHS.STORYBOARDS + ':filename', | ||
57 | asyncMiddleware(getStoryboard), | ||
58 | handleStaticError | ||
59 | ) | ||
60 | |||
61 | lazyStaticRouter.use( | ||
36 | LAZY_STATIC_PATHS.VIDEO_CAPTIONS + ':filename', | 62 | LAZY_STATIC_PATHS.VIDEO_CAPTIONS + ':filename', |
37 | asyncMiddleware(getVideoCaption), | 63 | asyncMiddleware(getVideoCaption), |
38 | handleStaticError | 64 | handleStaticError |
@@ -53,88 +79,48 @@ export { | |||
53 | } | 79 | } |
54 | 80 | ||
55 | // --------------------------------------------------------------------------- | 81 | // --------------------------------------------------------------------------- |
82 | const avatarPermanentFileCache = new AvatarPermanentFileCache() | ||
56 | 83 | ||
57 | async function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) { | 84 | function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) { |
58 | const filename = req.params.filename | 85 | const filename = req.params.filename |
59 | 86 | ||
60 | if (actorImagePathUnsafeCache.has(filename)) { | 87 | return avatarPermanentFileCache.lazyServe({ filename, res, next }) |
61 | return res.sendFile(actorImagePathUnsafeCache.get(filename), { maxAge: STATIC_MAX_AGE.SERVER }) | 88 | } |
62 | } | ||
63 | |||
64 | const image = await ActorImageModel.loadByName(filename) | ||
65 | if (!image) return res.status(HttpStatusCode.NOT_FOUND_404).end() | ||
66 | |||
67 | if (image.onDisk === false) { | ||
68 | if (!image.fileUrl) return res.status(HttpStatusCode.NOT_FOUND_404).end() | ||
69 | |||
70 | logger.info('Lazy serve remote actor image %s.', image.fileUrl) | ||
71 | |||
72 | try { | ||
73 | await downloadActorImageFromWorker({ | ||
74 | filename: image.filename, | ||
75 | fileUrl: image.fileUrl, | ||
76 | size: getActorImageSize(image), | ||
77 | type: image.type | ||
78 | }) | ||
79 | } catch (err) { | ||
80 | logger.warn('Cannot process remote actor image %s.', image.fileUrl, { err }) | ||
81 | return res.status(HttpStatusCode.NOT_FOUND_404).end() | ||
82 | } | ||
83 | |||
84 | image.onDisk = true | ||
85 | image.save() | ||
86 | .catch(err => logger.error('Cannot save new actor image disk state.', { err })) | ||
87 | } | ||
88 | |||
89 | const path = image.getPath() | ||
90 | |||
91 | actorImagePathUnsafeCache.set(filename, path) | ||
92 | |||
93 | return res.sendFile(path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }, (err: any) => { | ||
94 | if (!err) return | ||
95 | |||
96 | // It seems this actor image is not on the disk anymore | ||
97 | if (err.status === HttpStatusCode.NOT_FOUND_404 && !image.isOwned()) { | ||
98 | logger.error('Cannot lazy serve actor image %s.', filename, { err }) | ||
99 | 89 | ||
100 | actorImagePathUnsafeCache.delete(filename) | 90 | // --------------------------------------------------------------------------- |
91 | const videoMiniaturePermanentFileCache = new VideoMiniaturePermanentFileCache() | ||
101 | 92 | ||
102 | image.onDisk = false | 93 | function getThumbnail (req: express.Request, res: express.Response, next: express.NextFunction) { |
103 | image.save() | 94 | const filename = req.params.filename |
104 | .catch(err => logger.error('Cannot save new actor image disk state.', { err })) | ||
105 | } | ||
106 | 95 | ||
107 | return next(err) | 96 | return videoMiniaturePermanentFileCache.lazyServe({ filename, res, next }) |
108 | }) | ||
109 | } | 97 | } |
110 | 98 | ||
111 | function getActorImageSize (image: MActorImage): { width: number, height: number } { | 99 | // --------------------------------------------------------------------------- |
112 | if (image.width && image.height) { | 100 | |
113 | return { | 101 | async function getPreview (req: express.Request, res: express.Response) { |
114 | height: image.height, | 102 | const result = await VideoPreviewsSimpleFileCache.Instance.getFilePath(req.params.filename) |
115 | width: image.width | 103 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
116 | } | ||
117 | } | ||
118 | 104 | ||
119 | return ACTOR_IMAGES_SIZE[image.type][0] | 105 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) |
120 | } | 106 | } |
121 | 107 | ||
122 | async function getPreview (req: express.Request, res: express.Response) { | 108 | async function getStoryboard (req: express.Request, res: express.Response) { |
123 | const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename) | 109 | const result = await VideoStoryboardsSimpleFileCache.Instance.getFilePath(req.params.filename) |
124 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 110 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
125 | 111 | ||
126 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) | 112 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) |
127 | } | 113 | } |
128 | 114 | ||
129 | async function getVideoCaption (req: express.Request, res: express.Response) { | 115 | async function getVideoCaption (req: express.Request, res: express.Response) { |
130 | const result = await VideosCaptionCache.Instance.getFilePath(req.params.filename) | 116 | const result = await VideoCaptionsSimpleFileCache.Instance.getFilePath(req.params.filename) |
131 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 117 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
132 | 118 | ||
133 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) | 119 | return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) |
134 | } | 120 | } |
135 | 121 | ||
136 | async function getTorrent (req: express.Request, res: express.Response) { | 122 | async function getTorrent (req: express.Request, res: express.Response) { |
137 | const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename) | 123 | const result = await VideoTorrentsSimpleFileCache.Instance.getFilePath(req.params.filename) |
138 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() | 124 | if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() |
139 | 125 | ||
140 | // Torrents still use the old naming convention (video uuid + .torrent) | 126 | // Torrents still use the old naming convention (video uuid + .torrent) |