]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/object-storage/proxy.ts
Increase test timeouts
[github/Chocobozzz/PeerTube.git] / server / lib / object-storage / proxy.ts
CommitLineData
0c9668f7
C
1import express from 'express'
2import { PassThrough, pipeline } from 'stream'
3import { GetObjectCommandOutput } from '@aws-sdk/client-s3'
4import { buildReinjectVideoFileTokenQuery } from '@server/controllers/shared/m3u8-playlist'
5import { logger } from '@server/helpers/logger'
6import { StreamReplacer } from '@server/helpers/stream-replacer'
7import { MStreamingPlaylist, MVideo } from '@server/types/models'
8import { HttpStatusCode } from '@shared/models'
9import { injectQueryToPlaylistUrls } from '../hls'
10import { getHLSFileReadStream, getWebTorrentFileReadStream } from './videos'
11
12export async function proxifyWebTorrentFile (options: {
13 req: express.Request
14 res: express.Response
15 filename: string
16}) {
17 const { req, res, filename } = options
18
19 logger.debug('Proxifying WebTorrent file %s from object storage.', filename)
20
21 try {
22 const { response: s3Response, stream } = await getWebTorrentFileReadStream({
23 filename,
24 rangeHeader: req.header('range')
25 })
26
27 setS3Headers(res, s3Response)
28
29 return stream.pipe(res)
30 } catch (err) {
31 return handleObjectStorageFailure(res, err)
32 }
33}
34
35export async function proxifyHLS (options: {
36 req: express.Request
37 res: express.Response
38 playlist: MStreamingPlaylist
39 video: MVideo
40 filename: string
41 reinjectVideoFileToken: boolean
42}) {
43 const { req, res, playlist, video, filename, reinjectVideoFileToken } = options
44
45 logger.debug('Proxifying HLS file %s from object storage.', filename)
46
47 try {
48 const { response: s3Response, stream } = await getHLSFileReadStream({
49 playlist: playlist.withVideo(video),
50 filename,
51 rangeHeader: req.header('range')
52 })
53
54 setS3Headers(res, s3Response)
55
56 const streamReplacer = reinjectVideoFileToken
57 ? new StreamReplacer(line => injectQueryToPlaylistUrls(line, buildReinjectVideoFileTokenQuery(req, filename.endsWith('master.m3u8'))))
58 : new PassThrough()
59
60 return pipeline(
61 stream,
62 streamReplacer,
63 res,
64 err => {
65 if (!err) return
66
67 handleObjectStorageFailure(res, err)
68 }
69 )
70 } catch (err) {
71 return handleObjectStorageFailure(res, err)
72 }
73}
74
75// ---------------------------------------------------------------------------
76// Private
77// ---------------------------------------------------------------------------
78
79function handleObjectStorageFailure (res: express.Response, err: Error) {
80 if (err.name === 'NoSuchKey') {
81 logger.debug('Could not find key in object storage to proxify private HLS video file.', { err })
82 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
83 }
84
85 return res.fail({
86 status: HttpStatusCode.INTERNAL_SERVER_ERROR_500,
87 message: err.message,
88 type: err.name
89 })
90}
91
92function setS3Headers (res: express.Response, s3Response: GetObjectCommandOutput) {
93 if (s3Response.$metadata.httpStatusCode === HttpStatusCode.PARTIAL_CONTENT_206) {
94 res.setHeader('Content-Range', s3Response.ContentRange)
95 res.status(HttpStatusCode.PARTIAL_CONTENT_206)
96 }
97}