fix(playback): canonicalize base URL scheme case
FFmpeg's protocol lookup is case-sensitive, so a stored "Https://" base URL reaches mpv verbatim through the direct-play string concat and fails with "Protocol not found" (API calls survive because Dart's Uri lowercases the scheme). Canonicalize at Jellyfin URL intake and in the connection constructor so persisted configs self-heal on load, and register mpv-escaped (https\://) redaction variants so option-value logs stop leaking the server host. close #1465
This commit is contained in:
@@ -177,6 +177,16 @@ void main() {
|
||||
expect(r1.contains('server.example.com'), isFalse);
|
||||
expect(r2.contains('server.example.com'), isFalse);
|
||||
});
|
||||
|
||||
test('redacts the mpv-escaped form used in option-value logs', () {
|
||||
LogRedactionManager.registerServerUrl('https://server.example.com');
|
||||
// mpv echoes list options like sub-files with ':' escaped as '\:'.
|
||||
final result = LogRedactionManager.redact(
|
||||
r"Setting option 'sub-files' = 'https\://server.example.com/Videos/1/Subtitles/0/0/Stream.srt' (flags = 16)",
|
||||
);
|
||||
expect(result.contains('server.example.com'), isFalse);
|
||||
expect(result.contains('[REDACTED_URL]'), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('registerCustomValue', () {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/utils/url_utils.dart';
|
||||
|
||||
void main() {
|
||||
group('stripTrailingSlash', () {
|
||||
test('removes a single trailing slash', () {
|
||||
expect(stripTrailingSlash('https://host/'), 'https://host');
|
||||
});
|
||||
|
||||
test('trims whitespace and leaves slashless input unchanged', () {
|
||||
expect(stripTrailingSlash(' https://host '), 'https://host');
|
||||
expect(stripTrailingSlash(''), '');
|
||||
});
|
||||
});
|
||||
|
||||
group('canonicalizeBaseUrl', () {
|
||||
test('lowercases a mixed-case scheme (#1465)', () {
|
||||
// FFmpeg's protocol lookup is case-sensitive; "Https://" reaching the
|
||||
// player as a raw string fails with "Protocol not found".
|
||||
expect(canonicalizeBaseUrl('Https://jellyfin.example.com'), 'https://jellyfin.example.com');
|
||||
expect(canonicalizeBaseUrl('HTTPS://jellyfin.example.com'), 'https://jellyfin.example.com');
|
||||
});
|
||||
|
||||
test('only touches the scheme, not host/path/query', () {
|
||||
expect(canonicalizeBaseUrl('HTTP://Host.Example.com:8096/JellyFin'), 'http://Host.Example.com:8096/JellyFin');
|
||||
});
|
||||
|
||||
test('strips trailing slash and trims whitespace', () {
|
||||
expect(canonicalizeBaseUrl(' Https://host:8096/jellyfin/ '), 'https://host:8096/jellyfin');
|
||||
});
|
||||
|
||||
test('leaves schemeless input unchanged', () {
|
||||
expect(canonicalizeBaseUrl('host:8096'), 'host:8096');
|
||||
expect(canonicalizeBaseUrl('Host.example.com'), 'Host.example.com');
|
||||
expect(canonicalizeBaseUrl(''), '');
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user