From 0c44a35eb8d640005a9c40a9c6293d688513b78e Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 8 Feb 2026 03:54:22 +0100 Subject: [PATCH] feat: log raw API connections --- lib/services/plex_auth_service.dart | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/lib/services/plex_auth_service.dart b/lib/services/plex_auth_service.dart index 530229c4..b4695e16 100644 --- a/lib/services/plex_auth_service.dart +++ b/lib/services/plex_auth_service.dart @@ -9,6 +9,38 @@ import '../models/user_switch_response.dart'; import '../utils/app_logger.dart'; import '../utils/connection_constants.dart'; +/// Redacts the middle of an IP address or hostname for safe logging. +/// E.g. `192.168.1.50` → `192.***.***.50`, `my.server.example.com` → `my.***.***. com`. +String _redactHost(String host) { + // Strip brackets from IPv6 + final bare = host.startsWith('[') && host.endsWith(']') + ? host.substring(1, host.length - 1) + : host; + + // IPv6 + if (bare.contains(':')) { + final parts = bare.split(':'); + if (parts.length > 2) { + return '${parts.first}:***:${parts.last}'; + } + return bare; + } + + // IPv4 + final ipParts = bare.split('.'); + if (ipParts.length == 4 && ipParts.every((p) => int.tryParse(p) != null)) { + return '${ipParts.first}.***.***.${ipParts.last}'; + } + + // Hostname + final hostParts = bare.split('.'); + if (hostParts.length >= 3) { + return '${hostParts.first}.***.${hostParts.last}'; + } + + return bare; +} + class PlexAuthService { static const String _appName = 'Plezy'; static const String _plexApiBase = 'https://plex.tv/api/v2'; @@ -380,6 +412,20 @@ class PlexServer { error: {'preferred': preferredUri, 'candidateCount': totalCandidates}, ); + for (final conn in connections) { + final redactedUri = conn.uri.replaceAll( + RegExp(r'//[^:/]+'), + '//${_redactHost(conn.address)}', + ); + appLogger.d('Raw API connection', error: { + 'uri': redactedUri, + 'address': _redactHost(conn.address), + 'local': conn.local, + 'relay': conn.relay, + 'protocol': conn.protocol, + }); + } + _ConnectionCandidate? firstCandidate; // Fast-path: if we have a cached working URI, probe it with a short timeout