// ===----------------------------------------------------------------------=== // // This source file is part of the Hummingbird DocC Middleware open source project // // Copyright (c) 2025 Röck+Cöde VoF. and the Hummingbird DocC Middleware project authors // Licensed under the EUPL 1.2 or later. // // See LICENSE for license information // See CONTRIBUTORS for the list of Hummingbird DocC Middleware project authors // // ===----------------------------------------------------------------------=== import protocol Hummingbird.FileProvider import struct Hummingbird.LocalFileSystem import struct Logging.Logger /// A middleware that proxies requests to `DocC` documentation containers within a hosting app. public struct DocCMiddleware { // MARK: Properties /// A type that contains the parameters to configure the middleware. let configuration: Configuration /// A type that conforms to a protocol that defines file system interactions. let fileProvider: FileSystemProvider /// A type that interacts with the logging system. let logger: Logger /// A use case that checks whether a received URI could be processed or not. private let checkURI: CheckURIUseCase = .init() // MARK: Initializers /// Initializes this middleware. /// - Parameters: /// - configuration: A type that contains the parameters to configure the middleware. /// - logger: A type that interacts with the logging system. public init( configuration: Configuration, logger: Logger ) where FileSystemProvider == LocalFileSystem { self.init( configuration: configuration, fileProvider: LocalFileSystem( rootFolder: configuration.folderRoot, threadPool: configuration.threadPool, logger: logger ), logger: logger, ) } /// Initializes this middleware with a concrete file provider type. /// - Parameters: /// - configuration: A type that contains the parameters to configure the middleware. /// - fileProvider: A type that conforms to the protocol that defines file system interactions. /// - logger: A type that interacts with the logging system. init( configuration: Configuration, fileProvider: FileSystemProvider, logger: Logger, ) { self.logger = logger self.configuration = configuration self.fileProvider = fileProvider self.prepareURIPath = .init(uriRoot: configuration.uriRoot) self.redirectURI = .init(logger: logger) self.serveURI = .init( fileProvider: fileProvider, logger: logger ) } } // MARK: - RouterMiddleware extension DocCMiddleware: RouterMiddleware { // MARK: Type aliases public typealias Context = RequestContext public typealias Input = Request public typealias Output = Response // MARK: Functions public func handle( _ input: Input, context: any Context, next: (Input, any Context) async throws -> Output ) async throws -> Output { guard let uri = checkURI(input.uri) else { return try await next(input, context) } return try await next(input, context) } }