import 'package:localstore/localstore.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; 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(); } void toDisk() async { final db = Localstore.instance; await db .collection('meta') .doc('server') .set({'host': host, 'port': port, 'path': path, 'tag': tag}); } static Future fromDisk() async { final db = Localstore.instance; final data = await db.collection('meta').doc('server').get(); return OutbagServer( tag: data?['tag'], host: data?['host'], path: data?['path'], port: data?['port']); } } 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(); }