feat(api): add server-side caching for requests that could benefit (#3463)

* feat(api): add server-side caching for requests that could benefit for them

* fix(tests): do not cache responses while in tests

* fix: remove commented out leftover code

* chore(deps): update dependency html-webpack-plugin to v5.5.4

* Bundle embedded web app

* fix: remove caching for web app assets under test

* chore(tests): re-enable temporarily disabled test

* chore(deps): update dependency typescript to v5.3.3

* Bundle embedded web app

* chore(deps): update dependency npm to v10.2.5

* Bundle embedded web app

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Owncast <owncast@owncast.online>
This commit is contained in:
Gabe Kangas
2023-12-09 16:31:50 -08:00
committed by GitHub
parent b6efe49086
commit 2217f0614a
21 changed files with 316 additions and 119 deletions

View File

@@ -9,9 +9,9 @@ request = request('http://127.0.0.1:8080');
var ajv = new Ajv();
var nodeInfoSchema = jsonfile.readFileSync('schema/nodeinfo_2.0.json');
const serverName = 'owncast.server.test'
const serverURL = 'http://' + serverName
const fediUsername = 'streamer'
const serverName = 'owncast.server.test';
const serverURL = 'http://' + serverName;
const fediUsername = 'streamer';
test('disable federation', async (done) => {
const res = await sendAdminRequest('config/federation/enable', false);
@@ -59,10 +59,7 @@ test('verify responses of /federation/ when federation is disabled', async (done
});
test('set required parameters and enable federation', async (done) => {
const res1 = await sendAdminRequest(
'config/serverurl',
serverURL
);
const res1 = await sendAdminRequest('config/serverurl', serverURL);
const res2 = await sendAdminRequest(
'config/federation/username',
fediUsername
@@ -73,28 +70,47 @@ test('set required parameters and enable federation', async (done) => {
test('verify responses of /.well-known/webfinger when federation is enabled', async (done) => {
const resNoResource = request.get('/.well-known/webfinger').expect(400);
const resBadResource = request.get(
'/.well-known/webfinger?resource=' + fediUsername + '@' + serverName
).expect(400);
const resBadResource2 = request.get(
'/.well-known/webfinger?resource=notacct:' + fediUsername + '@' + serverName
).expect(400);
const resBadServer = request.get(
'/.well-known/webfinger?resource=acct:' + fediUsername + '@not' + serverName
).expect(404);
const resBadUser = request.get(
'/.well-known/webfinger?resource=acct:not' + fediUsername + '@' + serverName
).expect(404);
const resNoAccept = request.get(
'/.well-known/webfinger?resource=acct:' + fediUsername + '@' + serverName
).expect(200)
const resBadResource = request
.get('/.well-known/webfinger?resource=' + fediUsername + '@' + serverName)
.expect(400);
const resBadResource2 = request
.get(
'/.well-known/webfinger?resource=notacct:' +
fediUsername +
'@' +
serverName
)
.expect(400);
const resBadServer = request
.get(
'/.well-known/webfinger?resource=acct:' +
fediUsername +
'@not' +
serverName
)
.expect(404);
const resBadUser = request
.get(
'/.well-known/webfinger?resource=acct:not' +
fediUsername +
'@' +
serverName
)
.expect(404);
const resNoAccept = request
.get(
'/.well-known/webfinger?resource=acct:' + fediUsername + '@' + serverName
)
.expect(200)
.expect('Content-Type', /json/)
.then((res) => {
parseJson(res.text);
});
const resWithAccept = request.get(
'/.well-known/webfinger?resource=acct:' + fediUsername + '@' + serverName
).expect(200)
const resWithAccept = request
.get(
'/.well-known/webfinger?resource=acct:' + fediUsername + '@' + serverName
)
.expect(200)
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.then((res) => {
@@ -104,14 +120,16 @@ test('verify responses of /.well-known/webfinger when federation is enabled', as
});
test('verify responses of /.well-known/host-meta when federation is enabled', async (done) => {
const res = request.get('/.well-known/host-meta')
const res = request
.get('/.well-known/host-meta')
.expect(200)
.expect('Content-Type', /xml/);
done();
});
test('verify responses of /.well-known/nodeinfo when federation is enabled', async (done) => {
const res = request.get('/.well-known/nodeinfo')
const res = request
.get('/.well-known/nodeinfo')
.expect(200)
.expect('Content-Type', /json/)
.then((res) => {
@@ -121,7 +139,8 @@ test('verify responses of /.well-known/nodeinfo when federation is enabled', asy
});
test('verify responses of /.well-known/x-nodeinfo2 when federation is enabled', async (done) => {
const res = request.get('/.well-known/x-nodeinfo2')
const res = request
.get('/.well-known/x-nodeinfo2')
.expect(200)
.expect('Content-Type', /json/)
.then((res) => {
@@ -143,7 +162,8 @@ test('verify responses of /nodeinfo/2.0 when federation is enabled', async (done
});
test('verify responses of /api/v1/instance when federation is enabled', async (done) => {
const res = request.get('/api/v1/instance')
const res = request
.get('/api/v1/instance')
.expect(200)
.expect('Content-Type', /json/)
.then((res) => {
@@ -153,15 +173,17 @@ test('verify responses of /api/v1/instance when federation is enabled', async (d
});
test('verify responses of /federation/user/ when federation is enabled', async (done) => {
const resNoAccept = request.get('/federation/user/')
.expect(307);
const resWithAccept = request.get('/federation/user/')
const resNoAccept = request.get('/federation/user/').expect(307);
const resWithAccept = request
.get('/federation/user/')
.set('Accept', 'application/json')
.expect(404);
const resWithAcceptWrongUsername = request.get('/federation/user/not' + fediUsername)
const resWithAcceptWrongUsername = request
.get('/federation/user/not' + fediUsername)
.set('Accept', 'application/json')
.expect(404);
const resWithAcceptUsername = request.get('/federation/user/' + fediUsername)
const resWithAcceptUsername = request
.get('/federation/user/' + fediUsername)
.set('Accept', 'application/json')
.expect(200)
.expect('Content-Type', /json/)
@@ -172,9 +194,9 @@ test('verify responses of /federation/user/ when federation is enabled', async (
});
test('verify responses of /federation/ when federation is enabled', async (done) => {
const resNoAccept = request.get('/federation/')
.expect(307);
const resWithAccept = request.get('/federation/')
const resNoAccept = request.get('/federation/').expect(307);
const resWithAccept = request
.get('/federation/')
.set('Accept', 'application/json')
.expect(404);
done();

View File

@@ -3,91 +3,91 @@
set -e
function install_ffmpeg() {
# install a specific version of ffmpeg
# install a specific version of ffmpeg
FFMPEG_VER="4.4.1"
FFMPEG_PATH="$(pwd)/ffmpeg-$FFMPEG_VER"
PATH=$FFMPEG_PATH:$PATH
FFMPEG_VER="4.4.1"
FFMPEG_PATH="$(pwd)/ffmpeg-$FFMPEG_VER"
PATH=$FFMPEG_PATH:$PATH
if ! [[ -d "$FFMPEG_PATH" ]]; then
mkdir "$FFMPEG_PATH"
fi
if ! [[ -d "$FFMPEG_PATH" ]]; then
mkdir "$FFMPEG_PATH"
fi
pushd "$FFMPEG_PATH" >/dev/null
pushd "$FFMPEG_PATH" >/dev/null
if [[ -x "$FFMPEG_PATH/ffmpeg" ]]; then
ffmpeg_version=$("$FFMPEG_PATH/ffmpeg" -version | awk -F 'ffmpeg version' '{print $2}' | awk 'NR==1{print $1}')
if [[ -x "$FFMPEG_PATH/ffmpeg" ]]; then
if [[ "$ffmpeg_version" == "$FFMPEG_VER-static" ]]; then
popd >/dev/null
return 0
else
mv "$FFMPEG_PATH/ffmpeg" "$FFMPEG_PATH/ffmpeg.bk" || rm -f "$FFMPEG_PATH/ffmpeg"
fi
fi
ffmpeg_version=$("$FFMPEG_PATH/ffmpeg" -version | awk -F 'ffmpeg version' '{print $2}' | awk 'NR==1{print $1}')
rm -f ffmpeg.zip
curl -sL --fail https://github.com/ffbinaries/ffbinaries-prebuilt/releases/download/v${FFMPEG_VER}/ffmpeg-${FFMPEG_VER}-linux-64.zip --output ffmpeg.zip >/dev/null
unzip -o ffmpeg.zip >/dev/null && rm -f ffmpeg.zip
chmod +x ffmpeg
PATH=$FFMPEG_PATH:$PATH
if [[ "$ffmpeg_version" == "$FFMPEG_VER-static" ]]; then
popd >/dev/null
return 0
else
mv "$FFMPEG_PATH/ffmpeg" "$FFMPEG_PATH/ffmpeg.bk" || rm -f "$FFMPEG_PATH/ffmpeg"
fi
fi
popd >/dev/null
rm -f ffmpeg.zip
curl -sL --fail https://github.com/ffbinaries/ffbinaries-prebuilt/releases/download/v${FFMPEG_VER}/ffmpeg-${FFMPEG_VER}-linux-64.zip --output ffmpeg.zip >/dev/null
unzip -o ffmpeg.zip >/dev/null && rm -f ffmpeg.zip
chmod +x ffmpeg
PATH=$FFMPEG_PATH:$PATH
popd >/dev/null
}
function start_owncast() {
# Build and run owncast from source
echo "Building owncast..."
pushd "$(git rev-parse --show-toplevel)" >/dev/null
go build -o owncast main.go
# Build and run owncast from source
echo "Building owncast..."
pushd "$(git rev-parse --show-toplevel)" >/dev/null
go build -o owncast main.go
echo "Running owncast..."
./owncast -database "$TEMP_DB" &
SERVER_PID=$!
popd >/dev/null
echo "Running owncast..."
./owncast -disableResponseCaching -database "$TEMP_DB" &
SERVER_PID=$!
popd >/dev/null
sleep 5
sleep 5
}
function start_stream() {
# Start streaming the test file over RTMP to the local owncast instance.
../../ocTestStream.sh &
STREAM_PID=$!
# Start streaming the test file over RTMP to the local owncast instance.
../../ocTestStream.sh &
STREAM_PID=$!
echo "Waiting for stream to start..."
sleep 12
echo "Waiting for stream to start..."
sleep 12
}
function update_storage_config() {
echo "Configuring external storage to use ${S3_BUCKET}..."
echo "Configuring external storage to use ${S3_BUCKET}..."
# Hard-coded to admin:abc123 for auth
curl --fail 'http://localhost:8080/api/admin/config/s3' \
-H 'Authorization: Basic YWRtaW46YWJjMTIz' \
--data-raw "{\"value\":{\"accessKey\":\"${S3_ACCESS_KEY}\",\"acl\":\"\",\"bucket\":\"${S3_BUCKET}\",\"enabled\":true,\"endpoint\":\"${S3_ENDPOINT}\",\"region\":\"${S3_REGION}\",\"secret\":\"${S3_SECRET}\",\"servingEndpoint\":\"\"}}"
# Hard-coded to admin:abc123 for auth
curl --fail 'http://localhost:8080/api/admin/config/s3' \
-H 'Authorization: Basic YWRtaW46YWJjMTIz' \
--data-raw "{\"value\":{\"accessKey\":\"${S3_ACCESS_KEY}\",\"acl\":\"\",\"bucket\":\"${S3_BUCKET}\",\"enabled\":true,\"endpoint\":\"${S3_ENDPOINT}\",\"region\":\"${S3_REGION}\",\"secret\":\"${S3_SECRET}\",\"servingEndpoint\":\"\"}}"
}
function kill_with_kids() {
# kill a process and all its children (by pid)! return no error.
# kill a process and all its children (by pid)! return no error.
if [[ -n $1 ]]; then
mapfile -t CHILDREN_PID_LIST < <(ps --ppid "$1" -o pid= &>/dev/null || true)
for child_pid in "${CHILDREN_PID_LIST[@]}"; do
kill "$child_pid" &>/dev/null || true
wait "$child_pid" &>/dev/null || true
done
kill "$1" &>/dev/null || true
wait "$1" &>/dev/null || true
fi
if [[ -n $1 ]]; then
mapfile -t CHILDREN_PID_LIST < <(ps --ppid "$1" -o pid= &>/dev/null || true)
for child_pid in "${CHILDREN_PID_LIST[@]}"; do
kill "$child_pid" &>/dev/null || true
wait "$child_pid" &>/dev/null || true
done
kill "$1" &>/dev/null || true
wait "$1" &>/dev/null || true
fi
}
function finish() {
echo "Cleaning up..."
kill_with_kids "$STREAM_PID"
kill "$SERVER_PID" &>/dev/null || true
wait "$SERVER_PID" &>/dev/null || true
echo "Cleaning up..."
kill_with_kids "$STREAM_PID"
kill "$SERVER_PID" &>/dev/null || true
wait "$SERVER_PID" &>/dev/null || true
rm -fr "$TEMP_DB"
}