Repository: vapor/vapor
File: Sources/Vapor/Middleware/FileMiddleware.swift (Swift)

Code before:
            
            // If the default file doesn't exist, pass on request
            guard FileManager.default.fileExists(atPath: absPath) else {
                return next.respond(to: request)
            }
        }
        
        // stream the file
        let res = request.fileio.streamFile(at: absPath)
        return request.eventLoop.makeSucceededFuture(res)
    }
}

#if canImport(Foundation)
extension FileMiddleware {
    /// Creates a new `FileMiddleware` for a server contained in an Xcode Project.
    ///
    /// - parameters:
    ///     - bundle: The Bundle which contains the files to serve.
    ///     - publicDirectory: The public directory to serve files from.
    ///     - defaultFile: The name of the default file to look for and serve if a request hits any public directory. Starting with `/` implies
    ///     an absolute path from the public directory root. If `nil`, no default files are served.
    ///
    /// - important: Make sure the public directory you wish to serve files from is included in the `Copy Bundle Resources` build phase of your project
    /// - returns: A fully qualified FileMiddleware if the given `publicDirectory` can be served, `nil` otherwise
    public convenience init?(bundle: Bundle, publicDirectory: String = "Public", defaultFile: String? = nil) {
        guard let bundleResourceURL = bundle.resourceURL?.appendingPathComponent(publicDirectory.removeLeadingSlashes()),
              (try? bundleResourceURL.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true else {
            return nil
        }
        
        self.init(publicDirectory: bundleResourceURL.path, defaultFile: defaultFile)
    }
}
#endif

fileprivate extension String {
    /// Determines if input path is absolute based on a leading slash
    func isAbsolute() -> Bool {
        return self.hasPrefix("/")
    }

    /// Makes a path relative by removing all leading slashes
    func removeLeadingSlashes() -> String {
        var newPath = self
        while newPath.hasPrefix("/") {
            newPath.removeFirst()
        }
        return newPath
    }


Review comment (bug):
I don't like having a `nillable` API here, as providing the wrong information is an error for (almost) all use cases and would prevent further setup of the app.

I'm also wondering why we need `#if canImport(Foundation)` since it's virtually always present.

Code after:
        
        if isDir.boolValue {
            // If a directory, check for the default file
            guard let defaultFile = defaultFile else {
                return next.respond(to: request)
            }
            
            if defaultFile.isAbsolute() {
                absPath = self.publicDirectory + defaultFile.removeLeadingSlashes()
            } else {
                absPath = absPath.addTrailingSlash() + defaultFile
            }
            
            // If the default file doesn't exist, pass on request
            guard FileManager.default.fileExists(atPath: absPath) else {
                return next.respond(to: request)
            }
        }
        
        // stream the file
        let res = request.fileio.streamFile(at: absPath)
        return request.eventLoop.makeSucceededFuture(res)
    }

    /// Creates a new `FileMiddleware` for a server contained in an Xcode Project.
    ///
    /// - parameters:
    ///     - bundle: The Bundle which contains the files to serve.
    ///     - publicDirectory: The public directory to serve files from.
    ///     - defaultFile: The name of the default file to look for and serve if a request hits any public directory. Starting with `/` implies an absolute path from the public directory root. If `nil`, no default files are served.
    ///
    /// - important: Make sure the public directory you wish to serve files from is included in the `Copy Bundle Resources` build phase of your project
    /// - returns: A fully qualified FileMiddleware if the given `publicDirectory` can be served, throws a `BundleSetupError` otherwise
    public convenience init(bundle: Bundle, publicDirectory: String = "Public", defaultFile: String? = nil) throws {
        guard let bundleResourceURL = bundle.resourceURL else {
            throw BundleSetupError.bundleResourceURLIsNil
        }
        let publicDirectoryURL = bundleResourceURL.appendingPathComponent(publicDirectory.removeLeadingSlashes())
        guard (try? publicDirectoryURL.resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true else {
            throw BundleSetupError.publicDirectoryIsNotAFolder
        }
        
        self.init(publicDirectory: bundleResourceURL.path, defaultFile: defaultFile)
    }
}

fileprivate extension String {
    /// Determines if input path is absolute based on a leading slash
    func isAbsolute() -> Bool {
        return self.hasPrefix("/")
    }