diff --git a/lib/backend/resolve_url.dart b/lib/backend/resolve_url.dart new file mode 100644 index 0000000..0f87ccd --- /dev/null +++ b/lib/backend/resolve_url.dart @@ -0,0 +1,81 @@ +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(); +}