nc-photos/app/lib/api/api.dart

160 lines
4 KiB
Dart
Raw Normal View History

2021-04-10 06:28:12 +02:00
import 'dart:convert';
2022-12-08 16:39:13 +01:00
import 'package:flutter/foundation.dart';
2021-04-10 06:28:12 +02:00
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
2022-12-13 16:50:00 +01:00
import 'package:nc_photos/string_extension.dart';
2022-12-16 16:01:04 +01:00
import 'package:np_codegen/np_codegen.dart';
2022-12-08 16:39:13 +01:00
import 'package:to_string/to_string.dart';
2021-04-10 06:28:12 +02:00
import 'package:xml/xml.dart';
2022-12-08 16:39:13 +01:00
part 'api.g.dart';
2023-01-07 10:57:57 +01:00
part 'direct_api.dart';
part 'face_recognition_api.dart';
part 'files_api.dart';
part 'files_sharing_api.dart';
part 'systemtag_api.dart';
2022-12-08 16:39:13 +01:00
@toString
2021-04-10 06:28:12 +02:00
class Response {
Response(this.statusCode, this.headers, this.body);
bool get isGood => _isHttpStatusGood(statusCode);
@override
2022-12-08 16:39:13 +01:00
String toString() => _$toString();
2021-04-10 06:28:12 +02:00
final int statusCode;
2022-12-08 16:39:13 +01:00
@Format(r"...")
2021-04-10 06:28:12 +02:00
final Map<String, String> headers;
/// Content of the response body, String if isResponseString == true during
/// request, Uint8List otherwise
2022-12-08 16:39:13 +01:00
@Format(
2022-12-13 16:50:00 +01:00
r"${kDebugMode ? body.toString().replaceAll(RegExp(r'\n\t'), '').slice(0, 200) : '...'}")
2021-04-10 06:28:12 +02:00
final dynamic body;
}
class BasicAuth {
BasicAuth(this.username, this.password);
BasicAuth.fromAccount(Account account)
: this(
account.username2,
account.password,
);
@override
toString() {
final authString = base64.encode(utf8.encode("$username:$password"));
return "Basic $authString";
}
final String username;
final String password;
}
2022-12-16 16:01:04 +01:00
@npLog
2021-04-10 06:28:12 +02:00
class Api {
Api(Account account)
: _baseUrl = Uri.parse(account.url),
_auth = BasicAuth.fromAccount(account);
Api.fromBaseUrl(Uri baseUrl) : _baseUrl = baseUrl;
2021-04-10 06:28:12 +02:00
2022-07-08 16:52:18 +02:00
ApiFiles files() => ApiFiles(this);
2022-07-08 16:52:18 +02:00
ApiOcs ocs() => ApiOcs(this);
2022-07-08 16:52:18 +02:00
ApiSystemtags systemtags() => ApiSystemtags(this);
2022-07-08 16:52:18 +02:00
ApiSystemtagsRelations systemtagsRelations() => ApiSystemtagsRelations(this);
2021-04-10 06:28:12 +02:00
static String getAuthorizationHeaderValue(Account account) {
return BasicAuth.fromAccount(account).toString();
2021-04-10 06:28:12 +02:00
}
Future<Response> request(
String method,
String endpoint, {
2021-07-23 22:05:57 +02:00
Map<String, String>? header,
2021-08-05 06:50:36 +02:00
Map<String, String>? queryParameters,
2021-07-23 22:05:57 +02:00
String? body,
Uint8List? bodyBytes,
2021-04-10 06:28:12 +02:00
bool isResponseString = true,
}) async {
2021-08-05 06:50:36 +02:00
final url = _makeUri(endpoint, queryParameters: queryParameters);
final req = http.Request(method, url);
if (_auth != null) {
req.headers.addAll({
"authorization": _auth.toString(),
2021-04-10 06:28:12 +02:00
});
}
2021-04-10 06:28:12 +02:00
if (header != null) {
// turn all to lower case, since HTTP headers are case-insensitive, this
// smooths our processing (if any)
req.headers.addEntries(
header.entries.map((e) => MapEntry(e.key.toLowerCase(), e.value)));
}
if (body != null) {
req.body = body;
} else if (bodyBytes != null) {
req.bodyBytes = bodyBytes;
}
final response =
await http.Response.fromStream(await http.Client().send(req));
if (!_isHttpStatusGood(response.statusCode)) {
2021-05-23 19:26:28 +02:00
if (response.statusCode == 404) {
_log.severe(
"[request] HTTP $method (${response.statusCode}): $endpoint",
);
} else {
_log.severe(
"[request] HTTP $method (${response.statusCode}): $endpoint",
response.body,
);
}
2021-04-10 06:28:12 +02:00
}
return Response(response.statusCode, response.headers,
isResponseString ? response.body : response.bodyBytes);
}
2021-08-05 06:50:36 +02:00
Uri _makeUri(
String endpoint, {
Map<String, String>? queryParameters,
}) {
final path = _baseUrl.path + "/$endpoint";
if (_baseUrl.scheme == "http") {
return Uri.http(_baseUrl.authority, path, queryParameters);
2021-05-06 07:26:26 +02:00
} else {
return Uri.https(_baseUrl.authority, path, queryParameters);
2021-05-06 07:26:26 +02:00
}
}
final Uri _baseUrl;
BasicAuth? _auth;
2021-04-10 06:28:12 +02:00
}
bool _isHttpStatusGood(int status) => status ~/ 100 == 2;
2022-07-08 16:52:18 +02:00
class ApiOcs {
ApiOcs(this._api);
2021-08-05 07:48:32 +02:00
2022-07-08 16:52:18 +02:00
ApiOcsDav dav() => ApiOcsDav(this);
2022-07-08 16:52:18 +02:00
ApiOcsFacerecognition facerecognition() => ApiOcsFacerecognition(this);
2022-07-08 16:52:18 +02:00
ApiOcsFilesSharing filesSharing() => ApiOcsFilesSharing(this);
2021-08-05 07:48:32 +02:00
2021-09-15 08:58:06 +02:00
final Api _api;
2021-08-05 07:48:32 +02:00
}
2022-07-08 16:52:18 +02:00
class ApiOcsDav {
ApiOcsDav(this._ocs);
2021-08-05 07:48:32 +02:00
2022-07-08 16:52:18 +02:00
ApiOcsDavDirect direct() => ApiOcsDavDirect(this);
2021-08-05 07:48:32 +02:00
2022-07-08 16:52:18 +02:00
final ApiOcs _ocs;
2021-08-05 07:48:32 +02:00
}