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(); } 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 db = Localstore.instance; await db.collection('meta').doc('server').set(toMap()); } static Future fromDisk() async { final db = Localstore.instance; final data = await db.collection('meta').doc('server').get(); return OutbagServer.fromMap(data!); } } 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(); }