Skip to content

Commit

Permalink
feat(dynamite_runtime): make DynamiteClient extend http.Client
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolas Rimikis <leptopoda@users.noreply.github.com>
  • Loading branch information
Leptopoda committed Mar 1, 2024
1 parent 48233c5 commit 5db4f89
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 24 deletions.
53 changes: 35 additions & 18 deletions packages/dynamite/dynamite_runtime/lib/src/client/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:dynamite_runtime/http_client.dart';
import 'package:dynamite_runtime/src/utils/debug_mode.dart';
import 'package:dynamite_runtime/src/utils/uri.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';

/// A client for making network requests.
///
Expand All @@ -14,7 +15,7 @@ import 'package:http/http.dart' as http;
/// * [DynamiteRawResponse] as the raw response that can be serialized.
/// * [DynamiteApiException] as the exception that can be thrown in operations
/// * [DynamiteAuthentication] for providing authentication methods.
class DynamiteClient {
class DynamiteClient with http.BaseClient {
/// Creates a new dynamite network client.
///
/// If [httpClient] is not provided a default one will be created.
Expand Down Expand Up @@ -42,6 +43,7 @@ class DynamiteClient {
final Map<String, String>? baseHeaders;

/// The base http client.
@protected
final http.Client httpClient;

/// The optional cookie jar to persist the response cookies.
Expand Down Expand Up @@ -85,10 +87,6 @@ class DynamiteClient {
}) async {
final request = http.Request(method, uri);

if (baseHeaders != null) {
request.headers.addAll(baseHeaders!);
}

if (headers != null) {
request.headers.addAll(headers);
}
Expand All @@ -97,30 +95,49 @@ class DynamiteClient {
request.bodyBytes = body;
}

final response = await sendWithCookies(request);

if (validStatuses?.contains(response.statusCode) ?? true) {
return response;
} else {
if (kDebugMode) {
final result = await http.Response.fromStream(response);
throw DynamiteStatusCodeException.fromResponse(result);
} else {
throw DynamiteStatusCodeException(response.statusCode);
}
}
}

/// Sends an HTTP request and asynchronously returns the response.
///
/// Cookies are persisted in the [cookieJar] and loaded for requests.
Future<http.StreamedResponse> sendWithCookies(http.BaseRequest request) async {
if (cookieJar != null) {
final cookies = await cookieJar!.loadForRequest(uri);
final cookies = await cookieJar!.loadForRequest(request.url);
if (cookies.isNotEmpty) {
request.headers['cookie'] = cookies.join('; ');
}
}

final response = await httpClient.send(request);
final response = await send(request);

final cookieHeader = response.headersSplitValues['set-cookie'];
if (cookieHeader != null && cookieJar != null) {
final cookies = cookieHeader.map(Cookie.fromSetCookieValue).toList();
await cookieJar!.saveFromResponse(uri, cookies);
await cookieJar!.saveFromResponse(request.url, cookies);
}

if (validStatuses?.contains(response.statusCode) ?? true) {
return response;
} else {
if (kDebugMode) {
final result = await http.Response.fromStream(response);
throw DynamiteStatusCodeException.fromResponse(result);
} else {
throw DynamiteStatusCodeException(response.statusCode);
}
}
return response;
}

@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
// Do not overwrite request headers to avoid invalid requests.
baseHeaders?.forEach((key, value) {
request.headers.putIfAbsent(key, () => value);
});

return httpClient.send(request);
}
}
14 changes: 8 additions & 6 deletions packages/nextcloud/lib/src/webdav/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ class WebDavClient {
headers: headers,
);

request.headers.addAll({
...?rootClient.baseHeaders,
...?rootClient.authentications?.firstOrNull?.headers,
});
final authentication = rootClient.authentications?.firstOrNull;
if (authentication != null) {
request.headers.addAll(
authentication.headers,
);
}

// On web we need to send a CSRF token because we also send the cookies. In theory this should not be required as
// long as we send the OCS-APIRequest header, but the server has a bug that only triggers when you also send the
Expand All @@ -87,7 +89,7 @@ class WebDavClient {
// TODO: Fix this bug in server.
if (_kIsWeb) {
if (_token == null) {
final response = await rootClient.httpClient.get(Uri.parse('${rootClient.baseURL}/index.php'));
final response = await rootClient.get(Uri.parse('${rootClient.baseURL}/index.php'));
if (response.statusCode >= 300) {
throw DynamiteStatusCodeException(
response.statusCode,
Expand All @@ -103,7 +105,7 @@ class WebDavClient {
});
}

final response = await rootClient.httpClient.send(request);
final response = await rootClient.send(request);

if (response.statusCode >= 300) {
throw DynamiteStatusCodeException(
Expand Down

0 comments on commit 5db4f89

Please sign in to comment.