import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:worldhopper/models/opds_server.dart'; /// Service for handling HTTP Basic Authentication class AuthService { /// Create Dio client with authentication for a server Dio createAuthenticatedClient(OPDSServer server) { final dio = Dio( BaseOptions( connectTimeout: const Duration(seconds: 30), receiveTimeout: const Duration(seconds: 30), headers: { 'User-Agent': 'Worldhopper/1.0', 'Accept': 'application/atom+xml, application/xml, text/xml, */*', }, ), ); // Add authentication interceptor if credentials are provided if (server.requiresAuth) { dio.interceptors.add( InterceptorsWrapper( onRequest: (options, handler) { final authHeader = _generateBasicAuthHeader( server.username!, server.password!, ); options.headers['Authorization'] = authHeader; return handler.next(options); }, onError: (error, handler) { // Handle 401 Unauthorized errors if (error.response?.statusCode == 401) { // Could trigger re-authentication flow here } return handler.next(error); }, ), ); } // Add logging interceptor for debugging dio.interceptors.add( LogInterceptor( requestBody: false, responseBody: false, logPrint: (obj) { // Custom logging (can be integrated with a logging package) // print(obj); }, ), ); return dio; } /// Generate HTTP Basic Auth header String _generateBasicAuthHeader(String username, String password) { final credentials = '$username:$password'; final encoded = base64Encode(utf8.encode(credentials)); return 'Basic $encoded'; } /// Get authentication headers for image requests Map getAuthHeaders(OPDSServer server) { if (!server.requiresAuth) { return {}; } return { 'Authorization': _generateBasicAuthHeader( server.username!, server.password!, ), }; } /// Generate Basic Auth header from username and password static String generateBasicAuthHeader(String username, String password) { final credentials = '$username:$password'; final encoded = base64Encode(utf8.encode(credentials)); return 'Basic $encoded'; } }