createResource function
Future<void>
createResource(
- String resourceUrl, {
- dynamic content = '',
- bool isFile = true,
- bool replaceIfExist = true,
- ResourceContentType contentType = ResourceContentType.turtleText,
Asynchronously creates a resource (a file or directory / container) on a server using HTTP requests:
- PUT request: create or replace a resource if exists (e.g. an ACL file)
- POST request: create a resource (e.g. a TTL file or a directory)
Implementation
Future<void> createResource(
String resourceUrl, {
dynamic content = '',
bool isFile = true,
bool replaceIfExist = true,
ResourceContentType contentType = ResourceContentType.turtleText,
}) async {
// Sanity check
if (isFile) {
assert(!resourceUrl.endsWith('/'));
} else {
assert(resourceUrl.endsWith('/'));
assert(contentType == ResourceContentType.directory);
}
// Use PUT request for creating and replacing a file if it already exists
final put = (isFile && replaceIfExist) ? true : false;
final httpMethod = put ? http.put : http.post;
// Get the name and parent container URL of the resource to be created for
// POST request
late String name;
late String parentUrl;
if (!put) {
final items = resourceUrl.split('/');
final index = isFile ? items.length - 1 : items.length - 2;
name = items[index];
parentUrl = '${items.getRange(0, index).join('/')}/';
}
final (:accessToken, :dPopToken) = await getTokensForResource(
put ? resourceUrl : parentUrl,
put ? 'PUT' : 'POST',
);
var contentTypeStr = contentType.value;
if (contentType == ResourceContentType.auto) {
contentTypeStr =
mime.lookupMimeType(resourceUrl) ?? ResourceContentType.any.value;
}
final response = await httpMethod(
Uri.parse(put ? resourceUrl : parentUrl),
headers: <String, String>{
'Accept': '*/*',
'Authorization': 'DPoP $accessToken',
'Connection': 'keep-alive',
'Content-Type': contentTypeStr,
if (put)
'Content-Length': content is String
? utf8.encode(content).length.toString()
: (content as List<int>).length.toString(),
if (!put) 'Link': isFile ? fileTypeLink : dirTypeLink,
if (!put) 'Slug': name,
'DPoP': dPopToken,
},
body: content is String ? utf8.encode(content) : content,
);
if ([200, 201, 205].contains(response.statusCode)) {
return;
} else if (response.statusCode == 403) {
// No write permission at this location. Surface a typed, actionable error
// so callers (e.g. writing to another user's POD) can distinguish a
// permission problem from a generic failure.
throw AccessForbiddenException(
'Permission denied (HTTP 403) creating resource "$resourceUrl". '
'You do not have write access to this location on the POD.'
'\nERROR: ${response.body}',
);
} else {
throw Exception(
'Failed to create resource!'
'\nURL: $resourceUrl'
'\nERROR: ${response.body}',
);
}
}