1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-05 10:49:28 +02:00

Fix HLS private static path

This commit is contained in:
Chocobozzz 2025-04-08 07:16:54 +02:00
parent 473cd4f7ef
commit 94deeb0a8f
No known key found for this signature in database
GPG key ID: 583A612D890159BE
3 changed files with 47 additions and 18 deletions

View file

@ -61,7 +61,8 @@ describe('Test static endpoints validators', function () {
await makeGetRequest({ await makeGetRequest({
url: server.url, url: server.url,
token: server.accessToken, token: server.accessToken,
path: '/static/streaming-playlists/hls/private/' + privateVideo.uuid + '/' + privateM3U8.replace('.m3u8', '.mp4') path: '/static/streaming-playlists/hls/private/' + privateVideo.uuid + '/' + privateM3U8.replace('.m3u8', '.mp4'),
expectedStatus: HttpStatusCode.NOT_FOUND_404
}) })
}) })

View file

@ -5,7 +5,9 @@ import {
ensureCanAccessPrivateVideoHLSFiles, ensureCanAccessPrivateVideoHLSFiles,
ensureCanAccessVideoPrivateWebVideoFiles, ensureCanAccessVideoPrivateWebVideoFiles,
handleStaticError, handleStaticError,
optionalAuthenticate optionalAuthenticate,
privateHLSFileValidator,
privateM3U8PlaylistValidator
} from '@server/middlewares/index.js' } from '@server/middlewares/index.js'
import cors from 'cors' import cors from 'cors'
import express from 'express' import express from 'express'
@ -55,17 +57,20 @@ const privateHLSStaticMiddlewares = CONFIG.STATIC_FILES.PRIVATE_FILES_REQUIRE_AU
: [] : []
staticRouter.use( staticRouter.use(
STATIC_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:playlistNameWithoutExtension.m3u8', STATIC_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:playlistNameWithoutExtension([a-z0-9-]+).m3u8',
privateM3U8PlaylistValidator,
...privateHLSStaticMiddlewares, ...privateHLSStaticMiddlewares,
asyncMiddleware(servePrivateM3U8) asyncMiddleware(servePrivateM3U8)
) )
staticRouter.use( staticRouter.use(
STATIC_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS, STATIC_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename',
privateHLSFileValidator,
...privateHLSStaticMiddlewares, ...privateHLSStaticMiddlewares,
express.static(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, { fallthrough: false }), servePrivateHLSFile
handleStaticError
) )
// ---------------------------------------------------------------------------
staticRouter.use( staticRouter.use(
STATIC_PATHS.STREAMING_PLAYLISTS.HLS, STATIC_PATHS.STREAMING_PLAYLISTS.HLS,
express.static(DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC, { fallthrough: false }), express.static(DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC, { fallthrough: false }),
@ -80,6 +85,12 @@ export {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function servePrivateHLSFile (req: express.Request, res: express.Response) {
const path = join(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, req.params.videoUUID, req.params.filename)
return res.sendFile(path)
}
async function servePrivateM3U8 (req: express.Request, res: express.Response) { async function servePrivateM3U8 (req: express.Request, res: express.Response) {
const path = join(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, req.params.videoUUID, req.params.playlistNameWithoutExtension + '.m3u8') const path = join(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, req.params.videoUUID, req.params.playlistNameWithoutExtension + '.m3u8')
const filename = req.params.playlistNameWithoutExtension + '.m3u8' const filename = req.params.playlistNameWithoutExtension + '.m3u8'

View file

@ -1,6 +1,7 @@
import { HttpStatusCode } from '@peertube/peertube-models' import { HttpStatusCode } from '@peertube/peertube-models'
import { import {
exists, exists,
isSafeFilename,
isSafePeerTubeFilenameWithoutExtension, isSafePeerTubeFilenameWithoutExtension,
isUUIDValid, isUUIDValid,
toBooleanOrNull toBooleanOrNull
@ -28,7 +29,7 @@ const staticFileTokenBypass = new LRUCache<string, LRUValue>({
ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL
}) })
const ensureCanAccessVideoPrivateWebVideoFiles = [ export const ensureCanAccessVideoPrivateWebVideoFiles = [
query('videoFileToken').optional().custom(exists), query('videoFileToken').optional().custom(exists),
isValidVideoPasswordHeader(), isValidVideoPasswordHeader(),
@ -67,23 +68,44 @@ const ensureCanAccessVideoPrivateWebVideoFiles = [
} }
] ]
const ensureCanAccessPrivateVideoHLSFiles = [ export const privateM3U8PlaylistValidator = [
param('videoUUID') param('videoUUID')
.custom(isUUIDValid), .custom(isUUIDValid),
param('playlistNameWithoutExtension') param('playlistNameWithoutExtension')
.optional()
.custom(v => isSafePeerTubeFilenameWithoutExtension(v)), .custom(v => isSafePeerTubeFilenameWithoutExtension(v)),
query('videoFileToken')
.optional()
.custom(exists),
query('reinjectVideoFileToken') query('reinjectVideoFileToken')
.optional() .optional()
.customSanitizer(toBooleanOrNull) .customSanitizer(toBooleanOrNull)
.isBoolean().withMessage('Should be a valid reinjectVideoFileToken boolean'), .isBoolean().withMessage('Should be a valid reinjectVideoFileToken boolean'),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
return next()
}
]
export const privateHLSFileValidator = [
param('videoUUID')
.custom(isUUIDValid),
param('filename')
.custom(v => isSafeFilename(v)),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
return next()
}
]
export const ensureCanAccessPrivateVideoHLSFiles = [
query('videoFileToken')
.optional()
.custom(exists),
isValidVideoPasswordHeader(), isValidVideoPasswordHeader(),
async (req: express.Request, res: express.Response, next: express.NextFunction) => { async (req: express.Request, res: express.Response, next: express.NextFunction) => {
@ -124,11 +146,6 @@ const ensureCanAccessPrivateVideoHLSFiles = [
} }
] ]
export {
ensureCanAccessPrivateVideoHLSFiles,
ensureCanAccessVideoPrivateWebVideoFiles
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function isWebVideoAllowed (req: express.Request, res: express.Response) { async function isWebVideoAllowed (req: express.Request, res: express.Response) {