Skip to content

Commit

Permalink
refactor(nextcloud): add webdav headers to the request
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 Apr 2, 2024
1 parent 7246215 commit 972daf0
Showing 1 changed file with 90 additions and 41 deletions.
131 changes: 90 additions & 41 deletions packages/nextcloud/lib/src/webdav/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'package:nextcloud/src/webdav/props.dart';
import 'package:nextcloud/src/webdav/utils.dart';
import 'package:nextcloud/src/webdav/webdav.dart';
import 'package:nextcloud/utils.dart';
import 'package:universal_io/io.dart' hide HttpClient;
import 'package:universal_io/io.dart' show File, FileStat;

// ignore: do_not_use_environment
const bool _kIsWeb = bool.fromEnvironment('dart.library.js_util');
Expand All @@ -30,15 +30,6 @@ class WebDavClient {
Future<http.StreamedResponse> _send(
http.BaseRequest request,
) async {
final authentication = rootClient.authentications?.firstOrNull;
if (authentication != null) {
request.headers.addAll(
authentication.headers,
);
}

request.headers[HttpHeaders.contentTypeHeader] = 'application/xml';

// 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
// cookies. On non-web platforms we don't send the cookies so we are fine, but on web the browser always does it
Expand Down Expand Up @@ -78,23 +69,15 @@ class WebDavClient {
Future<WebDavMultistatus> _parseResponse(http.StreamedResponse response) async =>
WebDavMultistatus.fromXmlElement(await response.stream.xml);

Map<String, String> _getUploadHeaders({
required DateTime? lastModified,
required DateTime? created,
required int? contentLength,
}) =>
{
if (lastModified != null) 'X-OC-Mtime': lastModified.secondsSinceEpoch.toString(),
if (created != null) 'X-OC-CTime': created.secondsSinceEpoch.toString(),
if (contentLength != null) HttpHeaders.contentLengthHeader: contentLength.toString(),
};

/// Request to get the WebDAV capabilities of the server.
///
/// See:
/// * [options] for a complete operation executing this request.
http.BaseRequest options_Request() {
return http.Request('OPTIONS', _constructUri());
final request = http.Request('OPTIONS', _constructUri());

_addBaseHeaders(request);
return request;
}

/// Gets the WebDAV capabilities of the server.
Expand All @@ -116,7 +99,10 @@ class WebDavClient {
/// See:
/// * [mkcol] for a complete operation executing this request.
http.BaseRequest mkcol_Request(PathUri path) {
return http.Request('MKCOL', _constructUri(path));
final request = http.Request('MKCOL', _constructUri(path));

_addBaseHeaders(request);
return request;
}

/// Creates a collection at [path].
Expand All @@ -135,7 +121,10 @@ class WebDavClient {
/// See:
/// * [delete] for a complete operation executing this request.
http.BaseRequest delete_Request(PathUri path) {
return http.Request('DELETE', _constructUri(path));
final request = http.Request('DELETE', _constructUri(path));

_addBaseHeaders(request);
return request;
}

/// Deletes the resource at [path].
Expand All @@ -159,15 +148,16 @@ class WebDavClient {
DateTime? lastModified,
DateTime? created,
}) {
final headers = _getUploadHeaders(
final request = http.Request('PUT', _constructUri(path))..bodyBytes = localData;

_addUploadHeaders(
request,
lastModified: lastModified,
created: created,
contentLength: localData.length,
);

return http.Request('PUT', _constructUri(path))
..bodyBytes = localData
..headers.addAll(headers);
_addBaseHeaders(request);
return request;
}

/// Puts a new file at [path] with [localData] as content.
Expand Down Expand Up @@ -205,14 +195,16 @@ class WebDavClient {
int? contentLength,
void Function(double progress)? onProgress,
}) {
final headers = _getUploadHeaders(
final request = http.StreamedRequest('PUT', _constructUri(path));

_addBaseHeaders(request);
_addUploadHeaders(
request,
lastModified: lastModified,
created: created,
contentLength: contentLength,
);

final request = http.StreamedRequest('PUT', _constructUri(path))..headers.addAll(headers);

if (contentLength != null && onProgress != null) {
var uploaded = 0;

Expand Down Expand Up @@ -273,6 +265,8 @@ class WebDavClient {
DateTime? created,
void Function(double progress)? onProgress,
}) {
// Authentication and content-type headers are already set by the putStream_Request.
// No need to set them here.
return putStream_Request(
file.openRead(),
path,
Expand Down Expand Up @@ -316,7 +310,10 @@ class WebDavClient {
/// See:
/// * [get], [getStream] and [getFile] for complete operations executing this request.
http.BaseRequest get_Request(PathUri path) {
return http.Request('GET', _constructUri(path));
final request = http.Request('GET', _constructUri(path));

_addBaseHeaders(request);
return request;
}

/// Gets the content of the file at [path].
Expand Down Expand Up @@ -400,6 +397,7 @@ class WebDavClient {
request.headers['Depth'] = depth.value;
}

_addBaseHeaders(request);
return request;
}

Expand Down Expand Up @@ -434,12 +432,15 @@ class WebDavClient {
WebDavOcFilterRules filterRules, {
WebDavPropWithoutValues? prop,
}) {
return http.Request('REPORT', _constructUri(path))
final request = http.Request('REPORT', _constructUri(path))
..encoding = utf8
..body = WebDavOcFilterFiles(
filterRules: filterRules,
prop: prop ?? const WebDavPropWithoutValues(), // coverage:ignore-line
).toXmlElement(namespaces: namespaces).toXmlString();

_addBaseHeaders(request);
return request;
}

/// Runs the filter-files report with the [filterRules] on the resource at [path].
Expand Down Expand Up @@ -472,12 +473,15 @@ class WebDavClient {
WebDavProp? set,
WebDavPropWithoutValues? remove,
}) {
return http.Request('PROPPATCH', _constructUri(path))
final request = http.Request('PROPPATCH', _constructUri(path))
..encoding = utf8
..body = WebDavPropertyupdate(
set: set != null ? WebDavSet(prop: set) : null,
remove: remove != null ? WebDavRemove(prop: remove) : null,
).toXmlElement(namespaces: namespaces).toXmlString();

_addBaseHeaders(request);
return request;
}

/// Updates the props of the resource at [path].
Expand Down Expand Up @@ -520,9 +524,15 @@ class WebDavClient {
PathUri destinationPath, {
bool overwrite = false,
}) {
return http.Request('MOVE', _constructUri(sourcePath))
..headers['Destination'] = _constructUri(destinationPath).toString()
..headers['Overwrite'] = overwrite ? 'T' : 'F';
final request = http.Request('MOVE', _constructUri(sourcePath));

_addCopyHeaders(
request,
destinationPath: destinationPath,
overwrite: overwrite,
);
_addBaseHeaders(request);
return request;
}

/// Moves the resource from [sourcePath] to [destinationPath].
Expand Down Expand Up @@ -554,9 +564,15 @@ class WebDavClient {
PathUri destinationPath, {
bool overwrite = false,
}) {
return http.Request('COPY', _constructUri(sourcePath))
..headers['Destination'] = _constructUri(destinationPath).toString()
..headers['Overwrite'] = overwrite ? 'T' : 'F';
final request = http.Request('COPY', _constructUri(sourcePath));

_addCopyHeaders(
request,
destinationPath: destinationPath,
overwrite: overwrite,
);
_addBaseHeaders(request);
return request;
}

/// Copies the resource from [sourcePath] to [destinationPath].
Expand All @@ -578,4 +594,37 @@ class WebDavClient {

return _send(request);
}

void _addBaseHeaders(http.BaseRequest request) {
request.headers['content-type'] = 'application/xml';

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

static void _addUploadHeaders(
http.BaseRequest request, {
DateTime? lastModified,
DateTime? created,
int? contentLength,
}) {
if (lastModified != null) {
request.headers['X-OC-Mtime'] = lastModified.secondsSinceEpoch.toString();
}
if (created != null) {
request.headers['X-OC-CTime'] = created.secondsSinceEpoch.toString();
}
if (contentLength != null) {
request.headers['content-length'] = contentLength.toString();
}
}

void _addCopyHeaders(http.BaseRequest request, {required PathUri destinationPath, required bool overwrite}) {
request.headers['Destination'] = _constructUri(destinationPath).toString();
request.headers['Overwrite'] = overwrite ? 'T' : 'F';
}
}

0 comments on commit 972daf0

Please sign in to comment.