From e856d557ea06fbf60432b38d36d4b4fae45b4d66 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Thu, 22 Jun 2023 22:17:33 +0200 Subject: [PATCH 1/3] dynamite, dynamite_runtime, nextcloud: move http client to dynamite_runtime --- .../dynamite/lib/src/openapi_builder.dart | 253 ++---------------- .../dynamite_runtime/lib/http_client.dart | 1 + .../dynamite_runtime/lib/src/http_client.dart | 144 ++++++++++ .../dynamite/dynamite_runtime/pubspec.yaml | 2 + .../nextcloud/lib/src/nextcloud.openapi.dart | 117 ++------ packages/nextcloud/pubspec.yaml | 1 - 6 files changed, 179 insertions(+), 339 deletions(-) create mode 100644 packages/dynamite/dynamite_runtime/lib/http_client.dart create mode 100644 packages/dynamite/dynamite_runtime/lib/src/http_client.dart diff --git a/packages/dynamite/dynamite/lib/src/openapi_builder.dart b/packages/dynamite/dynamite/lib/src/openapi_builder.dart index 54604016..687f8bb4 100644 --- a/packages/dynamite/dynamite/lib/src/openapi_builder.dart +++ b/packages/dynamite/dynamite/lib/src/openapi_builder.dart @@ -67,48 +67,13 @@ class OpenAPIBuilder implements Builder { "import 'package:built_value/json_object.dart';", "import 'package:built_value/serializer.dart';", "import 'package:built_value/standard_json_plugin.dart';", - "import 'package:cookie_jar/cookie_jar.dart';", "import 'package:dynamite_runtime/content_string.dart';", - "import 'package:universal_io/io.dart';", + "import 'package:dynamite_runtime/http_client.dart';", '', - "export 'package:cookie_jar/cookie_jar.dart';", + "export 'package:dynamite_runtime/http_client.dart';", '', "part '${p.basename(outputId.changeExtension('.g.dart').path)}';", '', - Extension( - (final b) => b - ..name = '${prefix}HttpClientResponseBody' - ..on = refer('HttpClientResponse') - ..methods.addAll([ - Method( - (final b) => b - ..name = 'bodyBytes' - ..returns = refer('Future') - ..type = MethodType.getter - ..modifier = MethodModifier.async - ..body = const Code( - ''' - final chunks = await toList(); - if (chunks.isEmpty) { - return Uint8List(0); - } - return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element])); - ''', - ), - ), - Method( - (final b) => b - ..name = 'body' - ..returns = refer('Future') - ..type = MethodType.getter - ..modifier = MethodModifier.async - ..lambda = true - ..body = const Code( - 'utf8.decode(await bodyBytes)', - ), - ), - ]), - ).accept(emitter).toString(), Class( (final b) => b ..name = '${prefix}Response' @@ -116,20 +81,7 @@ class OpenAPIBuilder implements Builder { refer('T'), refer('U'), ]) - ..fields.addAll([ - Field( - (final b) => b - ..name = 'data' - ..type = refer('T') - ..modifier = FieldModifier.final$, - ), - Field( - (final b) => b - ..name = 'headers' - ..type = refer('U') - ..modifier = FieldModifier.final$, - ), - ]) + ..extend = refer('DynamiteResponse') ..constructors.add( Constructor( (final b) => b @@ -138,7 +90,7 @@ class OpenAPIBuilder implements Builder { (final name) => Parameter( (final b) => b ..name = name - ..toThis = true, + ..toSuper = true, ), ), ), @@ -157,61 +109,10 @@ class OpenAPIBuilder implements Builder { ), ), ).accept(emitter).toString(), - Class( - (final b) => b - ..name = 'RawResponse' - ..fields.addAll([ - Field( - (final b) => b - ..name = 'statusCode' - ..type = refer('int') - ..modifier = FieldModifier.final$, - ), - Field( - (final b) => b - ..name = 'headers' - ..type = refer('Map') - ..modifier = FieldModifier.final$, - ), - Field( - (final b) => b - ..name = 'body' - ..type = refer('Uint8List') - ..modifier = FieldModifier.final$, - ), - ]) - ..constructors.add( - Constructor( - (final b) => b - ..requiredParameters.addAll( - ['statusCode', 'headers', 'body'].map( - (final name) => Parameter( - (final b) => b - ..name = name - ..toThis = true, - ), - ), - ), - ), - ) - ..methods.add( - Method( - (final b) => b - ..name = 'toString' - ..returns = refer('String') - ..annotations.add(refer('override')) - ..lambda = true - ..body = const Code( - r"'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})'", - ), - ), - ), - ).accept(emitter).toString(), Class( (final b) => b ..name = '${prefix}ApiException' - ..extend = refer('RawResponse') - ..implements.add(refer('Exception')) + ..extend = refer('DynamiteApiException') ..constructors.addAll( [ Constructor( @@ -255,27 +156,6 @@ class OpenAPIBuilder implements Builder { ), ), ).accept(emitter).toString(), - if (hasAnySecurity) ...[ - Class( - (final b) => b - ..name = '${prefix}Authentication' - ..abstract = true - ..methods.addAll([ - Method( - (final b) => b - ..name = 'id' - ..type = MethodType.getter - ..returns = refer('String'), - ), - Method( - (final b) => b - ..name = 'headers' - ..type = MethodType.getter - ..returns = refer('Map'), - ), - ]), - ).accept(emitter).toString(), - ], ]; if (spec.components?.securitySchemes != null) { @@ -291,7 +171,7 @@ class OpenAPIBuilder implements Builder { final fields = ['username', 'password']; b ..name = '${prefix}HttpBasicAuthentication' - ..extend = refer('${prefix}Authentication') + ..extend = refer('DynamiteAuthentication') ..constructors.add( Constructor( (final b) => b @@ -352,7 +232,7 @@ class OpenAPIBuilder implements Builder { (final b) { b ..name = '${prefix}HttpBearerAuthentication' - ..extend = refer('${prefix}Authentication') + ..extend = refer('DynamiteAuthentication') ..constructors.add( Constructor( (final b) => b @@ -437,42 +317,7 @@ class OpenAPIBuilder implements Builder { (final b) { if (isRootClient) { b - ..fields.addAll([ - Field( - (final b) => b - ..name = 'baseURL' - ..type = refer('String') - ..modifier = FieldModifier.final$, - ), - Field( - (final b) => b - ..name = 'baseHeaders' - ..type = refer('Map') - ..modifier = FieldModifier.final$ - ..late = true, - ), - Field( - (final b) => b - ..name = 'httpClient' - ..type = refer('HttpClient') - ..modifier = FieldModifier.final$ - ..late = true, - ), - Field( - (final b) => b - ..name = 'cookieJar' - ..type = refer('CookieJar?') - ..modifier = FieldModifier.final$, - ), - if (hasAnySecurity) ...[ - Field( - (final b) => b - ..name = 'authentications' - ..type = refer('List<${prefix}Authentication>') - ..modifier = FieldModifier.final$, - ), - ], - ]) + ..extend = refer('DynamiteClient') ..constructors.add( Constructor( (final b) => b @@ -480,109 +325,45 @@ class OpenAPIBuilder implements Builder { Parameter( (final b) => b ..name = 'baseURL' - ..toThis = true, + ..toSuper = true, ), ) ..optionalParameters.addAll([ Parameter( (final b) => b ..name = 'baseHeaders' - ..type = refer('Map?') + ..toSuper = true ..named = true, ), Parameter( (final b) => b ..name = 'userAgent' - ..type = refer('String?') + ..toSuper = true ..named = true, ), Parameter( (final b) => b ..name = 'httpClient' - ..type = refer('HttpClient?') + ..toSuper = true ..named = true, ), Parameter( (final b) => b ..name = 'cookieJar' - ..toThis = true + ..toSuper = true ..named = true, ), if (hasAnySecurity) ...[ Parameter( (final b) => b ..name = 'authentications' - ..toThis = true - ..named = true - ..defaultTo = const Code('const []'), + ..toSuper = true + ..named = true, ), ], - ]) - ..body = const Code(''' - this.baseHeaders = { - ...?baseHeaders, - }; - this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent; - '''), + ]), ), - ) - ..methods.addAll([ - Method( - (final b) => b - ..name = 'doRequest' - ..returns = refer('Future') - ..modifier = MethodModifier.async - ..requiredParameters.addAll([ - Parameter( - (final b) => b - ..name = 'method' - ..type = refer('String'), - ), - Parameter( - (final b) => b - ..name = 'path' - ..type = refer('String'), - ), - Parameter( - (final b) => b - ..name = 'headers' - ..type = refer('Map'), - ), - Parameter( - (final b) => b - ..name = 'body' - ..type = refer('Uint8List?'), - ), - ]) - ..body = const Code(r''' - final uri = Uri.parse('$baseURL$path'); - final request = await httpClient.openUrl(method, uri); - for (final header in {...baseHeaders, ...headers}.entries) { - request.headers.add(header.key, header.value); - } - if (body != null) { - request.add(body.toList()); - } - if (cookieJar != null) { - request.cookies.addAll(await cookieJar!.loadForRequest(uri)); - } - - final response = await request.close(); - if (cookieJar != null) { - await cookieJar!.saveFromResponse(uri, response.cookies); - } - final responseHeaders = {}; - response.headers.forEach((final name, final values) { - responseHeaders[name] = values.last; - }); - return RawResponse( - response.statusCode, - responseHeaders, - await response.bodyBytes, - ); - '''), - ), - ]); + ); } else { b ..fields.add( diff --git a/packages/dynamite/dynamite_runtime/lib/http_client.dart b/packages/dynamite/dynamite_runtime/lib/http_client.dart new file mode 100644 index 00000000..1550b0eb --- /dev/null +++ b/packages/dynamite/dynamite_runtime/lib/http_client.dart @@ -0,0 +1 @@ +export 'src/http_client.dart'; diff --git a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart new file mode 100644 index 00000000..47877528 --- /dev/null +++ b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart @@ -0,0 +1,144 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cookie_jar/cookie_jar.dart'; +import 'package:universal_io/io.dart'; + +export 'package:cookie_jar/cookie_jar.dart'; + +extension DynamiteHttpClientResponseBody on HttpClientResponse { + Future get bodyBytes async { + final chunks = await toList(); + if (chunks.isEmpty) { + return Uint8List(0); + } + return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element])); + } + + Future get body async => utf8.decode(await bodyBytes); +} + +class DynamiteResponse { + DynamiteResponse( + this.data, + this.headers, + ); + + final T data; + + final U headers; + + @override + String toString() => 'DynamiteResponse(data: $data, headers: $headers)'; +} + +class RawResponse { + RawResponse( + this.statusCode, + this.headers, + this.body, + ); + + final int statusCode; + + final Map headers; + + final Uint8List body; + + @override + String toString() => 'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})'; +} + +class DynamiteApiException extends RawResponse implements Exception { + DynamiteApiException( + super.statusCode, + super.headers, + super.body, + ); + + @override + String toString() => + 'DynamiteApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})'; +} + +abstract class DynamiteAuthentication { + String get id; + Map get headers; +} + +class DynamiteHttpBasicAuthentication extends DynamiteAuthentication { + DynamiteHttpBasicAuthentication({ + required this.username, + required this.password, + }); + + final String username; + + final String password; + + @override + String get id => 'basic_auth'; + @override + Map get headers => { + 'Authorization': 'Basic ${base64.encode(utf8.encode('$username:$password'))}', + }; +} + +class DynamiteClient { + DynamiteClient( + this.baseURL, { + final Map? baseHeaders, + final String? userAgent, + final HttpClient? httpClient, + this.cookieJar, + this.authentications = const [], + }) { + this.baseHeaders = { + ...?baseHeaders, + }; + this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent; + } + + final String baseURL; + + late final Map baseHeaders; + + late final HttpClient httpClient; + + final CookieJar? cookieJar; + + final List authentications; + + Future doRequest( + final String method, + final String path, + final Map headers, + final Uint8List? body, + ) async { + final uri = Uri.parse('$baseURL$path'); + final request = await httpClient.openUrl(method, uri); + for (final header in {...baseHeaders, ...headers}.entries) { + request.headers.add(header.key, header.value); + } + if (body != null) { + request.add(body.toList()); + } + if (cookieJar != null) { + request.cookies.addAll(await cookieJar!.loadForRequest(uri)); + } + + final response = await request.close(); + if (cookieJar != null) { + await cookieJar!.saveFromResponse(uri, response.cookies); + } + final responseHeaders = {}; + response.headers.forEach((final name, final values) { + responseHeaders[name] = values.last; + }); + return RawResponse( + response.statusCode, + responseHeaders, + await response.bodyBytes, + ); + } +} diff --git a/packages/dynamite/dynamite_runtime/pubspec.yaml b/packages/dynamite/dynamite_runtime/pubspec.yaml index 19882ef8..addb6b13 100644 --- a/packages/dynamite/dynamite_runtime/pubspec.yaml +++ b/packages/dynamite/dynamite_runtime/pubspec.yaml @@ -7,6 +7,8 @@ environment: dependencies: built_value: ^8.5.0 + cookie_jar: ^4.0.5 + universal_io: ^2.2.2 dev_dependencies: build_runner: ^2.4.2 diff --git a/packages/nextcloud/lib/src/nextcloud.openapi.dart b/packages/nextcloud/lib/src/nextcloud.openapi.dart index 72dc15b4..d7dd424c 100644 --- a/packages/nextcloud/lib/src/nextcloud.openapi.dart +++ b/packages/nextcloud/lib/src/nextcloud.openapi.dart @@ -8,58 +8,24 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/json_object.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; -import 'package:cookie_jar/cookie_jar.dart'; import 'package:dynamite_runtime/content_string.dart'; -import 'package:universal_io/io.dart'; +import 'package:dynamite_runtime/http_client.dart'; -export 'package:cookie_jar/cookie_jar.dart'; +export 'package:dynamite_runtime/http_client.dart'; part 'nextcloud.openapi.g.dart'; -extension NextcloudHttpClientResponseBody on HttpClientResponse { - Future get bodyBytes async { - final chunks = await toList(); - if (chunks.isEmpty) { - return Uint8List(0); - } - return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element])); - } - - Future get body async => utf8.decode(await bodyBytes); -} - -class NextcloudResponse { +class NextcloudResponse extends DynamiteResponse { NextcloudResponse( - this.data, - this.headers, + super.data, + super.headers, ); - final T data; - - final U headers; - @override String toString() => 'NextcloudResponse(data: $data, headers: $headers)'; } -class RawResponse { - RawResponse( - this.statusCode, - this.headers, - this.body, - ); - - final int statusCode; - - final Map headers; - - final Uint8List body; - - @override - String toString() => 'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})'; -} - -class NextcloudApiException extends RawResponse implements Exception { +class NextcloudApiException extends DynamiteApiException { NextcloudApiException( super.statusCode, super.headers, @@ -77,12 +43,7 @@ class NextcloudApiException extends RawResponse implements Exception { 'NextcloudApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})'; } -abstract class NextcloudAuthentication { - String get id; - Map get headers; -} - -class NextcloudHttpBasicAuthentication extends NextcloudAuthentication { +class NextcloudHttpBasicAuthentication extends DynamiteAuthentication { NextcloudHttpBasicAuthentication({ required this.username, required this.password, @@ -100,63 +61,15 @@ class NextcloudHttpBasicAuthentication extends NextcloudAuthentication { }; } -class NextcloudClient { +class NextcloudClient extends DynamiteClient { NextcloudClient( - this.baseURL, { - final Map? baseHeaders, - final String? userAgent, - final HttpClient? httpClient, - this.cookieJar, - this.authentications = const [], - }) { - this.baseHeaders = { - ...?baseHeaders, - }; - this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent; - } - - final String baseURL; - - late final Map baseHeaders; - - late final HttpClient httpClient; - - final CookieJar? cookieJar; - - final List authentications; - - Future doRequest( - final String method, - final String path, - final Map headers, - final Uint8List? body, - ) async { - final uri = Uri.parse('$baseURL$path'); - final request = await httpClient.openUrl(method, uri); - for (final header in {...baseHeaders, ...headers}.entries) { - request.headers.add(header.key, header.value); - } - if (body != null) { - request.add(body.toList()); - } - if (cookieJar != null) { - request.cookies.addAll(await cookieJar!.loadForRequest(uri)); - } - - final response = await request.close(); - if (cookieJar != null) { - await cookieJar!.saveFromResponse(uri, response.cookies); - } - final responseHeaders = {}; - response.headers.forEach((final name, final values) { - responseHeaders[name] = values.last; - }); - return RawResponse( - response.statusCode, - responseHeaders, - await response.bodyBytes, - ); - } + super.baseURL, { + super.baseHeaders, + super.userAgent, + super.httpClient, + super.cookieJar, + super.authentications, + }); NextcloudCoreClient get core => NextcloudCoreClient(this); NextcloudNewsClient get news => NextcloudNewsClient(this); diff --git a/packages/nextcloud/pubspec.yaml b/packages/nextcloud/pubspec.yaml index 18885338..3babab32 100644 --- a/packages/nextcloud/pubspec.yaml +++ b/packages/nextcloud/pubspec.yaml @@ -8,7 +8,6 @@ environment: dependencies: built_collection: ^5.1.1 built_value: ^8.5.0 - cookie_jar: ^4.0.2 crypto: ^3.0.3 crypton: ^2.0.5 dynamite_runtime: From a08f62415e354f08dfcc9f0b5c68971123bc8902 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Thu, 22 Jun 2023 22:17:33 +0200 Subject: [PATCH 2/3] dynamite_runtime: more efficient decoding of responses --- .../dynamite/dynamite_runtime/lib/src/http_client.dart | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart index 47877528..6d873624 100644 --- a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart +++ b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart @@ -8,14 +8,12 @@ export 'package:cookie_jar/cookie_jar.dart'; extension DynamiteHttpClientResponseBody on HttpClientResponse { Future get bodyBytes async { - final chunks = await toList(); - if (chunks.isEmpty) { - return Uint8List(0); - } - return Uint8List.fromList(chunks.reduce((final value, final element) => [...value, ...element])); + final data = await expand((final element) => element).toList(); + + return Uint8List.fromList(data); } - Future get body async => utf8.decode(await bodyBytes); + Future get body => transform(utf8.decoder).join(); } class DynamiteResponse { From a541436dd48d4734a81bc2b3ba2766bf3265ac31 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Thu, 22 Jun 2023 22:17:33 +0200 Subject: [PATCH 3/3] dynamite, dynamite_runtime, nextcloud: improve data fetching performance --- .../dynamite/lib/src/openapi_builder.dart | 88 +++--- .../dynamite_runtime/lib/src/http_client.dart | 59 ++-- .../nextcloud/lib/src/nextcloud.openapi.dart | 277 +++++++++--------- packages/nextcloud/lib/src/webdav/client.dart | 8 +- 4 files changed, 218 insertions(+), 214 deletions(-) diff --git a/packages/dynamite/dynamite/lib/src/openapi_builder.dart b/packages/dynamite/dynamite/lib/src/openapi_builder.dart index 687f8bb4..58d28b2e 100644 --- a/packages/dynamite/dynamite/lib/src/openapi_builder.dart +++ b/packages/dynamite/dynamite/lib/src/openapi_builder.dart @@ -69,6 +69,7 @@ class OpenAPIBuilder implements Builder { "import 'package:built_value/standard_json_plugin.dart';", "import 'package:dynamite_runtime/content_string.dart';", "import 'package:dynamite_runtime/http_client.dart';", + "import 'package:universal_io/io.dart';", '', "export 'package:dynamite_runtime/http_client.dart';", '', @@ -113,37 +114,51 @@ class OpenAPIBuilder implements Builder { (final b) => b ..name = '${prefix}ApiException' ..extend = refer('DynamiteApiException') - ..constructors.addAll( - [ - Constructor( - (final b) => b - ..requiredParameters.addAll( - ['statusCode', 'headers', 'body'].map( - (final name) => Parameter( - (final b) => b - ..name = name - ..toSuper = true, - ), - ), - ), - ), - Constructor( - (final b) => b - ..name = 'fromResponse' - ..factory = true - ..lambda = true - ..requiredParameters.add( - Parameter( + ..constructors.add( + Constructor( + (final b) => b + ..requiredParameters.addAll( + ['statusCode', 'headers', 'body'].map( + (final name) => Parameter( (final b) => b - ..name = 'response' - ..type = refer('RawResponse'), + ..name = name + ..toSuper = true, ), - ) - ..body = Code('${prefix}ApiException(response.statusCode, response.headers, response.body,)'), - ), - ], + ), + ), + ), ) - ..methods.add( + ..methods.addAll([ + Method( + (final b) => b + ..name = 'fromResponse' + ..returns = refer('Future<${prefix}ApiException>') + ..static = true + ..modifier = MethodModifier.async + ..requiredParameters.add( + Parameter( + (final b) => b + ..name = 'response' + ..type = refer('HttpClientResponse'), + ), + ) + ..body = Block.of([ + const Code('final data = await response.bodyBytes;'), + const Code(''), + const Code('String body;'), + const Code('try {'), + const Code('body = utf8.decode(data);'), + const Code('} on FormatException {'), + const Code("body = 'binary';"), + const Code('}'), + const Code(''), + Code('return ${prefix}ApiException('), + const Code('response.statusCode,'), + const Code('response.responseHeaders,'), + const Code('body,'), + const Code(');'), + ]), + ), Method( (final b) => b ..name = 'toString' @@ -151,10 +166,10 @@ class OpenAPIBuilder implements Builder { ..annotations.add(refer('override')) ..lambda = true ..body = Code( - "'${prefix}ApiException(statusCode: \${super.statusCode}, headers: \${super.headers}, body: \${utf8.decode(super.body)})'", + "'${prefix}ApiException(statusCode: \$statusCode, headers: \$headers, body: \$body)'", ), ), - ), + ]), ).accept(emitter).toString(), ]; @@ -715,16 +730,21 @@ class OpenAPIBuilder implements Builder { if (mimeType == '*/*' || mimeType.startsWith('image/')) { dataType = 'Uint8List'; - dataValue = 'response.body'; + dataValue = 'response.bodyBytes'; } else if (mimeType.startsWith('text/')) { dataType = 'String'; - dataValue = 'utf8.decode(response.body)'; + dataValue = 'await response.body'; } else if (mimeType == 'application/json') { dataType = result.name; if (result.name == 'dynamic') { dataValue = ''; + } else if (result.name == 'String') { + // avoid unnecessary_await_in_return lint + dataValue = 'response.body'; + } else if (result is TypeResultEnum || result is TypeResultBase) { + dataValue = result.deserialize(result.decode('await response.body')); } else { - dataValue = result.deserialize(result.decode('utf8.decode(response.body)')); + dataValue = result.deserialize('await response.jsonBody'); } } else { throw Exception('Can not parse mime type "$mimeType"'); @@ -751,7 +771,7 @@ class OpenAPIBuilder implements Builder { code.write('}'); } code.write( - 'throw ${prefix}ApiException.fromResponse(response); // coverage:ignore-line\n', + 'throw await ${prefix}ApiException.fromResponse(response); // coverage:ignore-line\n', ); } else { b.returns = refer('Future'); diff --git a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart index 6d873624..f428be79 100644 --- a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart +++ b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart @@ -14,6 +14,17 @@ extension DynamiteHttpClientResponseBody on HttpClientResponse { } Future get body => transform(utf8.decoder).join(); + + Future get jsonBody => transform(utf8.decoder).transform(json.decoder).first; + + Map get responseHeaders { + final responseHeaders = {}; + headers.forEach((final name, final values) { + responseHeaders[name] = values.last; + }); + + return responseHeaders; + } } class DynamiteResponse { @@ -30,8 +41,8 @@ class DynamiteResponse { String toString() => 'DynamiteResponse(data: $data, headers: $headers)'; } -class RawResponse { - RawResponse( +class DynamiteApiException implements Exception { + DynamiteApiException( this.statusCode, this.headers, this.body, @@ -41,22 +52,10 @@ class RawResponse { final Map headers; - final Uint8List body; + final String body; @override - String toString() => 'RawResponse(statusCode: $statusCode, headers: $headers, body: ${utf8.decode(body)})'; -} - -class DynamiteApiException extends RawResponse implements Exception { - DynamiteApiException( - super.statusCode, - super.headers, - super.body, - ); - - @override - String toString() => - 'DynamiteApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})'; + String toString() => 'DynamiteApiException(statusCode: $statusCode, headers: $headers, body: $body)'; } abstract class DynamiteAuthentication { @@ -85,29 +84,24 @@ class DynamiteHttpBasicAuthentication extends DynamiteAuthentication { class DynamiteClient { DynamiteClient( this.baseURL, { - final Map? baseHeaders, + this.baseHeaders, final String? userAgent, final HttpClient? httpClient, this.cookieJar, this.authentications = const [], - }) { - this.baseHeaders = { - ...?baseHeaders, - }; - this.httpClient = (httpClient ?? HttpClient())..userAgent = userAgent; - } + }) : httpClient = (httpClient ?? HttpClient())..userAgent = userAgent; final String baseURL; - late final Map baseHeaders; + final Map? baseHeaders; - late final HttpClient httpClient; + final HttpClient httpClient; final CookieJar? cookieJar; final List authentications; - Future doRequest( + Future doRequest( final String method, final String path, final Map headers, @@ -115,7 +109,7 @@ class DynamiteClient { ) async { final uri = Uri.parse('$baseURL$path'); final request = await httpClient.openUrl(method, uri); - for (final header in {...baseHeaders, ...headers}.entries) { + for (final header in {...?baseHeaders, ...headers}.entries) { request.headers.add(header.key, header.value); } if (body != null) { @@ -129,14 +123,7 @@ class DynamiteClient { if (cookieJar != null) { await cookieJar!.saveFromResponse(uri, response.cookies); } - final responseHeaders = {}; - response.headers.forEach((final name, final values) { - responseHeaders[name] = values.last; - }); - return RawResponse( - response.statusCode, - responseHeaders, - await response.bodyBytes, - ); + + return response; } } diff --git a/packages/nextcloud/lib/src/nextcloud.openapi.dart b/packages/nextcloud/lib/src/nextcloud.openapi.dart index d7dd424c..1adb9c87 100644 --- a/packages/nextcloud/lib/src/nextcloud.openapi.dart +++ b/packages/nextcloud/lib/src/nextcloud.openapi.dart @@ -10,6 +10,7 @@ import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; @@ -32,15 +33,25 @@ class NextcloudApiException extends DynamiteApiException { super.body, ); - factory NextcloudApiException.fromResponse(final RawResponse response) => NextcloudApiException( - response.statusCode, - response.headers, - response.body, - ); + static Future fromResponse(final HttpClientResponse response) async { + final data = await response.bodyBytes; + + String body; + try { + body = utf8.decode(data); + } on FormatException { + body = 'binary'; + } + + return NextcloudApiException( + response.statusCode, + response.responseHeaders, + body, + ); + } @override - String toString() => - 'NextcloudApiException(statusCode: ${super.statusCode}, headers: ${super.headers}, body: ${utf8.decode(super.body)})'; + String toString() => 'NextcloudApiException(statusCode: $statusCode, headers: $headers, body: $body)'; } class NextcloudHttpBasicAuthentication extends DynamiteAuthentication { @@ -100,11 +111,11 @@ class NextcloudCoreClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudCoreServerStatus), )! as NextcloudCoreServerStatus; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getCapabilities() async { @@ -127,11 +138,11 @@ class NextcloudCoreClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudCoreServerCapabilities), )! as NextcloudCoreServerCapabilities; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getNavigationApps() async { @@ -154,11 +165,11 @@ class NextcloudCoreClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudCoreNavigationApps), )! as NextcloudCoreNavigationApps; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future initLoginFlow() async { @@ -176,11 +187,11 @@ class NextcloudCoreClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudCoreLoginFlowInit), )! as NextcloudCoreLoginFlowInit; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getLoginFlowResult({required final String token}) async { @@ -199,11 +210,11 @@ class NextcloudCoreClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudCoreLoginFlowResult), )! as NextcloudCoreLoginFlowResult; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getPreview({ @@ -250,9 +261,9 @@ class NextcloudCoreClient { body, ); if (response.statusCode == 200) { - return response.body; + return response.bodyBytes; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getDarkAvatar({ @@ -279,9 +290,9 @@ class NextcloudCoreClient { body, ); if (response.statusCode == 200) { - return response.body; + return response.bodyBytes; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getAvatar({ @@ -308,9 +319,9 @@ class NextcloudCoreClient { body, ); if (response.statusCode == 200) { - return response.body; + return response.bodyBytes; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future autocomplete({ @@ -350,11 +361,11 @@ class NextcloudCoreClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudCoreAutocompleteResult), )! as NextcloudCoreAutocompleteResult; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future deleteAppPassword() async { @@ -376,9 +387,9 @@ class NextcloudCoreClient { body, ); if (response.statusCode == 200) { - return JsonObject(utf8.decode(response.body)); + return JsonObject(await response.body); } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } @@ -407,11 +418,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsSupportedAPIVersions), )! as NextcloudNewsSupportedAPIVersions; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future listFolders() async { @@ -434,11 +445,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsListFolders), )! as NextcloudNewsListFolders; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future createFolder({required final String name}) async { @@ -462,11 +473,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsListFolders), )! as NextcloudNewsListFolders; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future renameFolder({ @@ -493,7 +504,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future deleteFolder({required final int folderId}) async { @@ -516,7 +527,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future markFolderAsRead({ @@ -543,7 +554,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future listFeeds() async { @@ -566,11 +577,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsListFeeds), )! as NextcloudNewsListFeeds; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future addFeed({ @@ -600,11 +611,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsListFeeds), )! as NextcloudNewsListFeeds; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future deleteFeed({required final int feedId}) async { @@ -627,7 +638,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future moveFeed({ @@ -656,7 +667,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future renameFeed({ @@ -683,7 +694,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future markFeedAsRead({ @@ -710,7 +721,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future listArticles({ @@ -758,11 +769,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsListArticles), )! as NextcloudNewsListArticles; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future listUpdatedArticles({ @@ -798,11 +809,11 @@ class NextcloudNewsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNewsListArticles), )! as NextcloudNewsListArticles; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future markArticleAsRead({required final int itemId}) async { @@ -825,7 +836,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future markArticleAsUnread({required final int itemId}) async { @@ -848,7 +859,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future starArticle({required final int itemId}) async { @@ -871,7 +882,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future unstarArticle({required final int itemId}) async { @@ -894,7 +905,7 @@ class NextcloudNewsClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } @@ -948,11 +959,11 @@ class NextcloudNotesClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(BuiltList, [FullType(NextcloudNotesNote)]), )! as BuiltList; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future createNote({ @@ -995,12 +1006,10 @@ class NextcloudNotesClient { body, ); if (response.statusCode == 200) { - return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), - specifiedType: const FullType(NextcloudNotesNote), - )! as NextcloudNotesNote; + return jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NextcloudNotesNote))! + as NextcloudNotesNote; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getNote({ @@ -1033,12 +1042,10 @@ class NextcloudNotesClient { body, ); if (response.statusCode == 200) { - return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), - specifiedType: const FullType(NextcloudNotesNote), - )! as NextcloudNotesNote; + return jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NextcloudNotesNote))! + as NextcloudNotesNote; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future updateNote({ @@ -1087,12 +1094,10 @@ class NextcloudNotesClient { body, ); if (response.statusCode == 200) { - return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), - specifiedType: const FullType(NextcloudNotesNote), - )! as NextcloudNotesNote; + return jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NextcloudNotesNote))! + as NextcloudNotesNote; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future deleteNote({required final int id}) async { @@ -1115,9 +1120,9 @@ class NextcloudNotesClient { body, ); if (response.statusCode == 200) { - return utf8.decode(response.body); + return response.body; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getSettings() async { @@ -1140,11 +1145,11 @@ class NextcloudNotesClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNotesSettings), )! as NextcloudNotesSettings; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future updateSettings({required final NextcloudNotesSettings notesSettings}) async { @@ -1173,11 +1178,11 @@ class NextcloudNotesClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNotesSettings), )! as NextcloudNotesSettings; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } @@ -1206,11 +1211,11 @@ class NextcloudNotificationsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNotificationsListNotifications), )! as NextcloudNotificationsListNotifications; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future deleteAllNotifications() async { @@ -1232,9 +1237,9 @@ class NextcloudNotificationsClient { body, ); if (response.statusCode == 200) { - return utf8.decode(response.body); + return response.body; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getNotification({required final int id}) async { @@ -1258,11 +1263,11 @@ class NextcloudNotificationsClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNotificationsGetNotification), )! as NextcloudNotificationsGetNotification; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future deleteNotification({required final int id}) async { @@ -1285,12 +1290,10 @@ class NextcloudNotificationsClient { body, ); if (response.statusCode == 200) { - return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), - specifiedType: const FullType(NextcloudEmptyOCS), - )! as NextcloudEmptyOCS; + return jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NextcloudEmptyOCS))! + as NextcloudEmptyOCS; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future registerDevice({ @@ -1320,11 +1323,11 @@ class NextcloudNotificationsClient { ); if (response.statusCode == 201) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudNotificationsPushServerRegistration), )! as NextcloudNotificationsPushServerRegistration; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future removeDevice() async { @@ -1346,9 +1349,9 @@ class NextcloudNotificationsClient { body, ); if (response.statusCode == 202) { - return utf8.decode(response.body); + return response.body; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future sendAdminNotification({ @@ -1379,12 +1382,10 @@ class NextcloudNotificationsClient { body, ); if (response.statusCode == 200) { - return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), - specifiedType: const FullType(NextcloudEmptyOCS), - )! as NextcloudEmptyOCS; + return jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NextcloudEmptyOCS))! + as NextcloudEmptyOCS; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } @@ -1413,11 +1414,11 @@ class NextcloudProvisioningApiClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudProvisioningApiUser), )! as NextcloudProvisioningApiUser; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getUser({required final String userId}) async { @@ -1441,11 +1442,11 @@ class NextcloudProvisioningApiClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudProvisioningApiUser), )! as NextcloudProvisioningApiUser; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } @@ -1475,11 +1476,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderCheckResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderCheckResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Set keepalive interval @@ -1508,11 +1509,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderSetKeepaliveResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderSetKeepaliveResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Request to create a new deviceId @@ -1539,11 +1540,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderCreateDeviceResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderCreateDeviceResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Request to get push messages @@ -1572,11 +1573,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 401) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderSyncDeviceResponse401ApplicationJson), )! as NextcloudUnifiedPushProviderSyncDeviceResponse401ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Delete a device @@ -1603,11 +1604,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderDeleteDeviceResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderDeleteDeviceResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Create an authorization token for a new 3rd party service @@ -1636,11 +1637,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderCreateAppResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderCreateAppResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Delete an authorization token @@ -1667,11 +1668,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderDeleteAppResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderDeleteAppResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Unifiedpush discovery Following specifications @@ -1698,11 +1699,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderUnifiedpushDiscoveryResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderUnifiedpushDiscoveryResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Receive notifications from 3rd parties @@ -1727,11 +1728,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 201) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderPushResponse201ApplicationJson), )! as NextcloudUnifiedPushProviderPushResponse201ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Matrix Gateway discovery @@ -1755,11 +1756,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderGatewayMatrixDiscoveryResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderGatewayMatrixDiscoveryResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } /// Matrix Gateway @@ -1783,11 +1784,11 @@ class NextcloudUnifiedPushProviderClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUnifiedPushProviderGatewayMatrixResponse200ApplicationJson), )! as NextcloudUnifiedPushProviderGatewayMatrixResponse200ApplicationJson; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } @@ -1816,11 +1817,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusGetPublicStatuses), )! as NextcloudUserStatusGetPublicStatuses; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getPublicStatus({required final String userId}) async { @@ -1844,11 +1845,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusGetPublicStatus), )! as NextcloudUserStatusGetPublicStatus; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getStatus() async { @@ -1871,11 +1872,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusGetStatus), )! as NextcloudUserStatusGetStatus; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future setStatus({required final NextcloudUserStatusType statusType}) async { @@ -1899,11 +1900,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusGetStatus), )! as NextcloudUserStatusGetStatus; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future setPredefinedMessage({ @@ -1933,11 +1934,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusGetStatus), )! as NextcloudUserStatusGetStatus; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future setCustomMessage({ @@ -1973,11 +1974,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusGetStatus), )! as NextcloudUserStatusGetStatus; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future clearMessage() async { @@ -1999,7 +2000,7 @@ class NextcloudUserStatusClient { if (response.statusCode == 200) { return; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future getPredefinedStatuses() async { @@ -2022,11 +2023,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusPredefinedStatuses), )! as NextcloudUserStatusPredefinedStatuses; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } Future heartbeat({required final NextcloudUserStatusType status}) async { @@ -2050,11 +2051,11 @@ class NextcloudUserStatusClient { ); if (response.statusCode == 200) { return jsonSerializers.deserialize( - json.decode(utf8.decode(response.body)), + await response.jsonBody, specifiedType: const FullType(NextcloudUserStatusHeartbeat), )! as NextcloudUserStatusHeartbeat; } - throw NextcloudApiException.fromResponse(response); // coverage:ignore-line + throw await NextcloudApiException.fromResponse(response); // coverage:ignore-line } } diff --git a/packages/nextcloud/lib/src/webdav/client.dart b/packages/nextcloud/lib/src/webdav/client.dart index d1aa4952..f7558019 100644 --- a/packages/nextcloud/lib/src/webdav/client.dart +++ b/packages/nextcloud/lib/src/webdav/client.dart @@ -29,7 +29,7 @@ class WebDavClient { ..persistentConnection = true; for (final header in { HttpHeaders.contentTypeHeader: 'application/xml', - ...rootClient.baseHeaders, + ...?rootClient.baseHeaders, if (headers != null) ...headers, if (rootClient.authentications.isNotEmpty) ...rootClient.authentications.first.headers, }.entries) { @@ -43,11 +43,7 @@ class WebDavClient { final response = await request.close(); if (!expectedCodes.contains(response.statusCode)) { - throw NextcloudApiException( - response.statusCode, - {}, // TODO - await response.bodyBytes, - ); + throw await NextcloudApiException.fromResponse(response); } return response;