diff --git a/lib/src/type_handlers/directory_type_handler.dart b/lib/src/type_handlers/directory_type_handler.dart index 0b869a4..7cd60e8 100644 --- a/lib/src/type_handlers/directory_type_handler.dart +++ b/lib/src/type_handlers/directory_type_handler.dart @@ -10,87 +10,81 @@ import '../extensions/request_helpers.dart'; import '../extensions/response_helpers.dart'; import 'type_handler.dart'; -TypeHandler get directoryTypeHandler => - TypeHandler((req, res, Directory directory) async { - directory = directory.absolute; - final usedRoute = req.route; - String? virtualPath; - if (usedRoute.contains('*')) { - virtualPath = req.uri.path - .substring(min(req.uri.path.length, usedRoute.indexOf('*'))); - } +TypeHandler get directoryTypeHandler => TypeHandler((req, res, Directory directory) async { + directory = directory.absolute; + final usedRoute = req.route; + final sep = Platform.pathSeparator; + String? virtualPath; + if (usedRoute.contains('*')) { + virtualPath = req.uri.path.substring(min(req.uri.path.length, usedRoute.indexOf('*'))); + } - if (req.method == 'GET' || req.method == 'HEAD') { - assert(usedRoute.contains('*'), - 'TypeHandler of type Directory GET request needs a route declaration that contains a wildcard (*). Found: $usedRoute'); + if (req.method == 'GET' || req.method == 'HEAD') { + assert( + usedRoute.contains('*'), + 'TypeHandler of type Directory GET request needs a route declaration that contains a wildcard (*). Found: $usedRoute', + ); - final filePath = - '${directory.path}/${Uri.decodeComponent(virtualPath!)}'; + var filePath = '${directory.path}${sep}${Uri.decodeComponent(virtualPath!)}'; - req.preventTraversal(filePath, directory); + filePath = filePath.replaceAll('/', Platform.pathSeparator); - req.log(() => 'Resolve virtual path: $virtualPath'); + req.preventTraversal(filePath, directory); - final fileCandidates = [ - File(filePath), - File('$filePath/index.html'), - File('$filePath/index.htm'), - ]; + req.log(() => 'Resolve virtual path: $virtualPath'); - try { - var match = fileCandidates.firstWhere((file) => file.existsSync()); - req.log(() => 'Respond with file: ${match.path}'); - await _respondWithFile(res, match, headerOnly: req.method == 'HEAD'); - } on StateError { - req.log(() => - 'Could not match with any file. Expected file at: $filePath'); - } - } - if (req.method == 'POST' || req.method == 'PUT') { - //Upload file - final body = await req.body; - - if (body is Map && body['file'] is HttpBodyFileUpload) { - if (virtualPath != null) { - req.preventTraversal('${directory.path}/$virtualPath', directory); - directory = Directory('${directory.path}/$virtualPath').absolute; - } - if (await directory.exists() == false) { - await directory.create(recursive: true); - } - final fileName = (body['file'] as HttpBodyFileUpload).filename; - - final fileToWrite = File('${directory.path}/$fileName'); - - req.preventTraversal(fileToWrite.path, directory); - - await fileToWrite.writeAsBytes( - (body['file'] as HttpBodyFileUpload).content as List); - final publicPath = - "${req.requestedUri.toString() + (virtualPath != null ? '/$virtualPath' : '')}/$fileName"; - req.log(() => 'Uploaded file $publicPath'); - - await res.json({'path': publicPath}); - } + final fileCandidates = [File(filePath), File('${filePath}index.html'), File('${filePath}index.htm')]; + + try { + var match = fileCandidates.firstWhere((file) => file.existsSync()); + req.log(() => 'Respond with file: ${match.path}'); + await _respondWithFile(res, match, headerOnly: req.method == 'HEAD'); + } on StateError { + req.log(() => 'Could not match with any file. Expected file at: $filePath'); + } + } + if (req.method == 'POST' || req.method == 'PUT') { + //Upload file + final body = await req.body; + + if (body is Map && body['file'] is HttpBodyFileUpload) { + if (virtualPath != null) { + req.preventTraversal('${directory.path}${sep}$virtualPath', directory); + directory = Directory('${directory.path}${sep}$virtualPath').absolute; } - if (req.method == 'DELETE') { - final fileToDelete = - File('${directory.path}/${Uri.decodeComponent(virtualPath!)}'); - - req.preventTraversal(fileToDelete.path, directory); - - if (await fileToDelete.exists()) { - await fileToDelete.delete(); - await res.json({'success': 'true'}); - } else { - res.statusCode = 404; - await res.json({'error': 'file not found'}); - } + if (await directory.exists() == false) { + await directory.create(recursive: true); } - }); + final fileName = (body['file'] as HttpBodyFileUpload).filename; + + final fileToWrite = File('${directory.path}${sep}$fileName'); + + req.preventTraversal(fileToWrite.path, directory); + + await fileToWrite.writeAsBytes((body['file'] as HttpBodyFileUpload).content as List); + final publicPath = + "${req.requestedUri.toString() + (virtualPath != null ? '${sep}$virtualPath' : '')}${sep}$fileName"; + req.log(() => 'Uploaded file $publicPath'); + + await res.json({'path': publicPath}); + } + } + if (req.method == 'DELETE') { + final fileToDelete = File('${directory.path}${sep}${Uri.decodeComponent(virtualPath!)}'); + + req.preventTraversal(fileToDelete.path, directory); + + if (await fileToDelete.exists()) { + await fileToDelete.delete(); + await res.json({'success': 'true'}); + } else { + res.statusCode = 404; + await res.json({'error': 'file not found'}); + } + } +}); -Future _respondWithFile(HttpResponse res, File file, - {bool headerOnly = false}) async { +Future _respondWithFile(HttpResponse res, File file, {bool headerOnly = false}) async { res.setContentTypeFromFile(file); // This is necessary to deal with 'HEAD' requests @@ -101,8 +95,7 @@ Future _respondWithFile(HttpResponse res, File file, } extension _Logger on HttpRequest { - void log(String Function() msgFn) => - alfred.logWriter(() => 'DirectoryTypeHandler: ${msgFn()}', LogType.debug); + void log(String Function() msgFn) => alfred.logWriter(() => 'DirectoryTypeHandler: ${msgFn()}', LogType.debug); void preventTraversal(String filePath, Directory absDir) { final check = File(filePath).absolute;