import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; const String wellKnownPath = "/.well-known/outbag/server"; const int defaultPort = 7223; Future fetchWellKnown(String host, int port) async { Uri uri = Uri(path: wellKnownPath, host: host, port: port, scheme: "https"); final resp = await http.get(uri); final json = jsonDecode(resp.body); return Uri(host: host, path: json['path'], port: json['port']); } class OutbagServer { final String host; final int port; final String path; final String tag; const OutbagServer( {required this.host, required this.port, required this.path, required this.tag}); String get base { return Uri( host: host, port: port, path: path, scheme: 'https', ).toString(); } factory OutbagServer.fromMap(Map data) { return OutbagServer( tag: data['tag'], host: data['host'], path: data['path'], port: data['port']); } Map toMap() { return {'host': host, 'port': port, 'path': path, 'tag': tag}; } Future toDisk() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('server-host', host); await prefs.setInt('server-port', port); await prefs.setString('server-path', path); await prefs.setString('server-tag', tag); } static Future fromDisk() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return OutbagServer( path: prefs.getString('server-path')!, port: prefs.getInt('server-port')!, tag: prefs.getString('server-tag')!, host: prefs.getString('server-host')!); } static Future removeDisk() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.remove('server-host'); await prefs.remove('server-port'); await prefs.remove('server-path'); await prefs.remove('server-tag'); } } Future getOutbagServerUrl(String tag) async { final rootUri = Uri.parse(tag.startsWith('https://') ? tag : 'https://$tag'); bool onRoot = rootUri.port == 443; try { final uri = await fetchWellKnown(rootUri.host, rootUri.port); return OutbagServer( host: rootUri.host, port: uri.port, path: uri.path, tag: onRoot ? rootUri.host : '${rootUri.host}:${uri.port}'); } catch (_) { if (onRoot) { final uri = await fetchWellKnown(rootUri.host, defaultPort); return OutbagServer( host: rootUri.host, port: uri.port, path: uri.path, tag: onRoot ? rootUri.host : '${rootUri.host}:${uri.port}'); } } throw Error(); }