From 8844acfdbc27a2fa438995d2e132e4e8dcf5a884 Mon Sep 17 00:00:00 2001 From: Vasily Fedorov Date: Tue, 9 Nov 2021 16:38:26 +0300 Subject: [PATCH] Respect symlinks when reading static mocks --- .../CatbirdApp/Stores/FileResponseStore.swift | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/Packages/CatbirdApp/Sources/CatbirdApp/Stores/FileResponseStore.swift b/Packages/CatbirdApp/Sources/CatbirdApp/Stores/FileResponseStore.swift index f6cbdc8..a85826b 100644 --- a/Packages/CatbirdApp/Sources/CatbirdApp/Stores/FileResponseStore.swift +++ b/Packages/CatbirdApp/Sources/CatbirdApp/Stores/FileResponseStore.swift @@ -1,6 +1,7 @@ import CatbirdAPI import Vapor import NIO +import Foundation final class FileResponseStore: ResponseStore { /// Path to the response body folder. @@ -21,7 +22,13 @@ final class FileResponseStore: ResponseStore { guard fileExists(atPath: path) else { return request.eventLoop.makeFailedFuture(Abort(.notFound)) } - let response = request.fileio.streamFile(at: path) + let realFilePath: String + if fileIsSymlink(atPath: path) { + realFilePath = destinationOfSymlink(atPath: path) + } else { + realFilePath = path + } + let response = request.fileio.streamFile(at: realFilePath) return request.eventLoop.makeSucceededFuture(response) } @@ -51,6 +58,31 @@ final class FileResponseStore: ResponseStore { return fileManger.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue } + private func fileIsSymlink(atPath path: String) -> Bool { + guard let fileAttributes = try? fileManger.attributesOfItem(atPath: path) else { + return false + } + guard fileAttributes[.type] as? FileAttributeType == .typeSymbolicLink else { + return false + } + return true + } + + private func destinationOfSymlink(atPath path: String) -> String { + guard let symLinkDestination = try? fileManger.destinationOfSymbolicLink(atPath: path) else { + return path + } + if fileExists(atPath: symLinkDestination) { + return symLinkDestination + } + let basePath = (path as NSString).deletingLastPathComponent as NSString + let symlinkFullPath = basePath.appendingPathComponent(symLinkDestination) + guard fileExists(atPath: symlinkFullPath) else { + return path + } + return symlinkFullPath + } + private func createDirectories(for filePath: String) throws { let url = URL(fileURLWithPath: filePath, isDirectory: false) // Remove file name