]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/object-storage-proxy.ts
Implement signup approval in server
[github/Chocobozzz/PeerTube.git] / server / controllers / object-storage-proxy.ts
CommitLineData
9ab330b9
C
1import cors from 'cors'
2import express from 'express'
71e3e879 3import { PassThrough, pipeline } from 'stream'
5a122ddd 4import { logger } from '@server/helpers/logger'
71e3e879 5import { StreamReplacer } from '@server/helpers/stream-replacer'
9ab330b9 6import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants'
71e3e879 7import { injectQueryToPlaylistUrls } from '@server/lib/hls'
9ab330b9
C
8import { getHLSFileReadStream, getWebTorrentFileReadStream } from '@server/lib/object-storage'
9import {
10 asyncMiddleware,
11 ensureCanAccessPrivateVideoHLSFiles,
12 ensureCanAccessVideoPrivateWebTorrentFiles,
5a122ddd 13 ensurePrivateObjectStorageProxyIsEnabled,
9ab330b9
C
14 optionalAuthenticate
15} from '@server/middlewares'
16import { HttpStatusCode } from '@shared/models'
71e3e879 17import { buildReinjectVideoFileTokenQuery, doReinjectVideoFileToken } from './shared/m3u8-playlist'
57e11a20 18import { GetObjectCommandOutput } from '@aws-sdk/client-s3'
9ab330b9
C
19
20const objectStorageProxyRouter = express.Router()
21
22objectStorageProxyRouter.use(cors())
23
24objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename',
5a122ddd 25 ensurePrivateObjectStorageProxyIsEnabled,
9ab330b9
C
26 optionalAuthenticate,
27 asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles),
28 asyncMiddleware(proxifyWebTorrent)
29)
30
31objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename',
5a122ddd 32 ensurePrivateObjectStorageProxyIsEnabled,
9ab330b9
C
33 optionalAuthenticate,
34 asyncMiddleware(ensureCanAccessPrivateVideoHLSFiles),
35 asyncMiddleware(proxifyHLS)
36)
37
38// ---------------------------------------------------------------------------
39
40export {
41 objectStorageProxyRouter
42}
43
44async function proxifyWebTorrent (req: express.Request, res: express.Response) {
45 const filename = req.params.filename
46
5a122ddd
C
47 logger.debug('Proxifying WebTorrent file %s from object storage.', filename)
48
9ab330b9 49 try {
57e11a20 50 const { response: s3Response, stream } = await getWebTorrentFileReadStream({
9ab330b9
C
51 filename,
52 rangeHeader: req.header('range')
53 })
54
57e11a20
C
55 setS3Headers(res, s3Response)
56
9ab330b9
C
57 return stream.pipe(res)
58 } catch (err) {
59 return handleObjectStorageFailure(res, err)
60 }
61}
62
63async function proxifyHLS (req: express.Request, res: express.Response) {
64 const playlist = res.locals.videoStreamingPlaylist
65 const video = res.locals.onlyVideo
66 const filename = req.params.filename
67
5a122ddd
C
68 logger.debug('Proxifying HLS file %s from object storage.', filename)
69
9ab330b9 70 try {
57e11a20 71 const { response: s3Response, stream } = await getHLSFileReadStream({
9ab330b9
C
72 playlist: playlist.withVideo(video),
73 filename,
74 rangeHeader: req.header('range')
75 })
76
57e11a20
C
77 setS3Headers(res, s3Response)
78
71e3e879
C
79 const streamReplacer = filename.endsWith('.m3u8') && doReinjectVideoFileToken(req)
80 ? new StreamReplacer(line => injectQueryToPlaylistUrls(line, buildReinjectVideoFileTokenQuery(req)))
81 : new PassThrough()
82
83 return pipeline(
84 stream,
85 streamReplacer,
86 res,
87 err => {
88 if (!err) return
89
90 handleObjectStorageFailure(res, err)
91 }
92 )
9ab330b9
C
93 } catch (err) {
94 return handleObjectStorageFailure(res, err)
95 }
96}
97
98function handleObjectStorageFailure (res: express.Response, err: Error) {
99 if (err.name === 'NoSuchKey') {
71e3e879 100 logger.debug('Could not find key in object storage to proxify private HLS video file.', { err })
9ab330b9
C
101 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
102 }
103
104 return res.fail({
105 status: HttpStatusCode.INTERNAL_SERVER_ERROR_500,
106 message: err.message,
107 type: err.name
108 })
109}
57e11a20
C
110
111function setS3Headers (res: express.Response, s3Response: GetObjectCommandOutput) {
112 if (s3Response.$metadata.httpStatusCode === HttpStatusCode.PARTIAL_CONTENT_206) {
113 res.status(HttpStatusCode.PARTIAL_CONTENT_206)
114 }
115}