X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fcontrollers%2Fobject-storage-proxy.ts;h=6bff05f14052d9237cd35cecbe65d35114cfc5b0;hb=09f3d81e0c8edebbe8f5698811ecfb165f942378;hp=6fedcfd8fcd9974e5109025d24247efdb58601cc;hpb=9ab330b90decf4edf152ff8e1d2948c065766b2c;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/controllers/object-storage-proxy.ts b/server/controllers/object-storage-proxy.ts index 6fedcfd8f..6bff05f14 100644 --- a/server/controllers/object-storage-proxy.ts +++ b/server/controllers/object-storage-proxy.ts @@ -1,26 +1,35 @@ import cors from 'cors' import express from 'express' +import { PassThrough, pipeline } from 'stream' +import { logger } from '@server/helpers/logger' +import { StreamReplacer } from '@server/helpers/stream-replacer' import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants' +import { injectQueryToPlaylistUrls } from '@server/lib/hls' import { getHLSFileReadStream, getWebTorrentFileReadStream } from '@server/lib/object-storage' import { asyncMiddleware, ensureCanAccessPrivateVideoHLSFiles, ensureCanAccessVideoPrivateWebTorrentFiles, + ensurePrivateObjectStorageProxyIsEnabled, optionalAuthenticate } from '@server/middlewares' import { HttpStatusCode } from '@shared/models' +import { buildReinjectVideoFileTokenQuery, doReinjectVideoFileToken } from './shared/m3u8-playlist' +import { GetObjectCommandOutput } from '@aws-sdk/client-s3' const objectStorageProxyRouter = express.Router() objectStorageProxyRouter.use(cors()) objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename', + ensurePrivateObjectStorageProxyIsEnabled, optionalAuthenticate, asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles), asyncMiddleware(proxifyWebTorrent) ) objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename', + ensurePrivateObjectStorageProxyIsEnabled, optionalAuthenticate, asyncMiddleware(ensureCanAccessPrivateVideoHLSFiles), asyncMiddleware(proxifyHLS) @@ -35,12 +44,16 @@ export { async function proxifyWebTorrent (req: express.Request, res: express.Response) { const filename = req.params.filename + logger.debug('Proxifying WebTorrent file %s from object storage.', filename) + try { - const stream = await getWebTorrentFileReadStream({ + const { response: s3Response, stream } = await getWebTorrentFileReadStream({ filename, rangeHeader: req.header('range') }) + setS3Headers(res, s3Response) + return stream.pipe(res) } catch (err) { return handleObjectStorageFailure(res, err) @@ -52,14 +65,31 @@ async function proxifyHLS (req: express.Request, res: express.Response) { const video = res.locals.onlyVideo const filename = req.params.filename + logger.debug('Proxifying HLS file %s from object storage.', filename) + try { - const stream = await getHLSFileReadStream({ + const { response: s3Response, stream } = await getHLSFileReadStream({ playlist: playlist.withVideo(video), filename, rangeHeader: req.header('range') }) - return stream.pipe(res) + setS3Headers(res, s3Response) + + const streamReplacer = filename.endsWith('.m3u8') && doReinjectVideoFileToken(req) + ? new StreamReplacer(line => injectQueryToPlaylistUrls(line, buildReinjectVideoFileTokenQuery(req, filename.endsWith('master.m3u8')))) + : new PassThrough() + + return pipeline( + stream, + streamReplacer, + res, + err => { + if (!err) return + + handleObjectStorageFailure(res, err) + } + ) } catch (err) { return handleObjectStorageFailure(res, err) } @@ -67,6 +97,7 @@ async function proxifyHLS (req: express.Request, res: express.Response) { function handleObjectStorageFailure (res: express.Response, err: Error) { if (err.name === 'NoSuchKey') { + logger.debug('Could not find key in object storage to proxify private HLS video file.', { err }) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) } @@ -76,3 +107,9 @@ function handleObjectStorageFailure (res: express.Response, err: Error) { type: err.name }) } + +function setS3Headers (res: express.Response, s3Response: GetObjectCommandOutput) { + if (s3Response.$metadata.httpStatusCode === HttpStatusCode.PARTIAL_CONTENT_206) { + res.status(HttpStatusCode.PARTIAL_CONTENT_206) + } +}