api.service.dart 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import 'dart:convert';
  2. import 'package:flutter/material.dart';
  3. import 'package:hive/hive.dart';
  4. import 'package:immich_mobile/constants/hive_box.dart';
  5. import 'package:immich_mobile/utils/url_helper.dart';
  6. import 'package:openapi/api.dart';
  7. import 'package:http/http.dart';
  8. class ApiService {
  9. late ApiClient _apiClient;
  10. late UserApi userApi;
  11. late AuthenticationApi authenticationApi;
  12. late OAuthApi oAuthApi;
  13. late AlbumApi albumApi;
  14. late AssetApi assetApi;
  15. late ServerInfoApi serverInfoApi;
  16. late DeviceInfoApi deviceInfoApi;
  17. ApiService() {
  18. if (Hive.isBoxOpen(userInfoBox)) {
  19. final endpoint = Hive.box(userInfoBox).get(serverEndpointKey) as String;
  20. if (endpoint.isNotEmpty) {
  21. setEndpoint(endpoint);
  22. }
  23. } else {
  24. debugPrint("Cannot init ApiServer endpoint, userInfoBox not open yet.");
  25. }
  26. }
  27. setEndpoint(String endpoint) {
  28. _apiClient = ApiClient(basePath: endpoint);
  29. userApi = UserApi(_apiClient);
  30. authenticationApi = AuthenticationApi(_apiClient);
  31. oAuthApi = OAuthApi(_apiClient);
  32. albumApi = AlbumApi(_apiClient);
  33. assetApi = AssetApi(_apiClient);
  34. serverInfoApi = ServerInfoApi(_apiClient);
  35. deviceInfoApi = DeviceInfoApi(_apiClient);
  36. }
  37. Future<String> resolveAndSetEndpoint(String serverUrl) async {
  38. final endpoint = await _resolveEndpoint(serverUrl);
  39. setEndpoint(endpoint);
  40. // Save in hivebox for next startup
  41. Hive.box(userInfoBox).put(serverEndpointKey, endpoint);
  42. return endpoint;
  43. }
  44. /// Takes a server URL and attempts to resolve the API endpoint.
  45. ///
  46. /// Input: [schema://]host[:port][/path]
  47. /// schema - optional (default: https)
  48. /// host - required
  49. /// port - optional (default: based on schema)
  50. /// path - optional
  51. Future<String> _resolveEndpoint(String serverUrl) async {
  52. final url = sanitizeUrl(serverUrl);
  53. // Check for /.well-known/immich
  54. final wellKnownEndpoint = await _getWellKnownEndpoint(url);
  55. if (wellKnownEndpoint.isNotEmpty) return wellKnownEndpoint;
  56. // Otherwise, assume the URL provided is the api endpoint
  57. return url;
  58. }
  59. Future<String> _getWellKnownEndpoint(String baseUrl) async {
  60. final Client client = Client();
  61. try {
  62. final res = await client.get(
  63. Uri.parse("$baseUrl/.well-known/immich"),
  64. headers: {"Accept": "application/json"},
  65. );
  66. if (res.statusCode == 200) {
  67. final data = jsonDecode(res.body);
  68. final endpoint = data['api']['endpoint'].toString();
  69. if (endpoint.startsWith('/')) {
  70. // Full URL is relative to base
  71. return "$baseUrl$endpoint";
  72. }
  73. return endpoint;
  74. }
  75. } catch (e) {
  76. debugPrint("Could not locate /.well-known/immich at $baseUrl");
  77. }
  78. return "";
  79. }
  80. setAccessToken(String accessToken) {
  81. _apiClient.addDefaultHeader('Authorization', 'Bearer $accessToken');
  82. }
  83. }