I am trying to get Mountebank to return the read in file stream pipe from my .ts
MPEG-2 file to the Mountebank injection so the client can receive the stream data and play the video. There is a useful Node implementation on how to read in the files and I got it to read in. the .m3u8
file but now it seems to get stuck with the first .ts
file.
Node seems to be reading the .ts
files as a stream and piping it to the response stream.pipe(res)
. I'm not sure how that translates to Mountebank. Here is what I have for Mountbank code:
Mountbank:
function (request, state, logger, callback) {
const path = require('path');
const fs = require('fs');
function _handleError(errorMessage, statusCode) {
logger.error(`[video-qoe-injection:responses]`, errorMessage);
return {
statusCode,
body: {}
}
}
function _sendFile(filepath) {
const data = fs.readFileSync(filepath, 'utf-8');
return {
statusCode: 200,
headers: {'Content-Type': 'application/vnd.apple.mpegurl'},
body: data
}
}
if (request && request.method === 'GET') {
if (path.extname(uri) === '.m3u8') {
filepath = path.join(M3U8_FILE_PATH);
return _sendFile(filepath);
}
} else if (path.extname(uri) === '.ts') {
filepath = path.join(TS_FILE_PATH)
let body = '';
const stream = fs.createReadStream(filepath, { bufferSize: 64 * 1024 });
stream.on('data', (data) => {
body += data.toString();
});
stream.on('end', () => {
const stubResponse = {
statusCode: 200,
headers: {'Content-Type': 'video/MP2T'},
body
}
callback(stubResponse);
});
}
}
I tried this with the pure Node implementation and it works, however, when I port this to Mountebank I get a console log error with the following error:
hls.0.12.4.min.js:1 Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.
player.js:57 Player error: mediaError - fragParsingError
Not sure what I'm missing here, does Mountebank not support stream responses? I even tried reading the .ts
file with const data = fs.readFileSync(filepath)
but hls.js doesn't seem to like that and getting a promise rejection.
I think you might need to simulate this using something a little more crude - from the documentation:
HTTP bodies will always be recorded as text, but mountebank does have the ability to respond in binary. If you want to set up a canned binary response, set the _mode to binary and base64 encode the body. mountebank will also try to preserve binary responses in proxies by looking at the Content-Encoding and Content-Type headers.
I have used this in the past, but only with a simple PDF file in a non-JS injection stub:
"responses": [
{
"is": {
"_mode": "binary",
"statusCode": 200,
"headers": {
"Content-Type": "application/pdf",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE"
},
"body": "U29tZVJhbmRvbUJhc2U2NA...<etc>"
}
}
]
I'd suggest trying a couple of things:
"responses": [
{
"is": {
"_mode": "binary",
"statusCode": 200,
"headers": {
"Content-Type": "video/MP2T",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET"
},
"body": "<% include ./YourBase64EncodedFilePathHere.txt %>"
}
}
]