import Configuration import Hummingbird import Logging import WebsiteCore /// Builds the website application. /// /// Reads the log level, server name, and static files location from the configuration, /// then assembles the router, server configuration, and logger. /// - Parameter reader: the configuration reader the values are read from. /// - Returns: the configured application, ready to run as a service. func application( reader: ConfigReader ) async -> some ApplicationProtocol { let logLevel = reader.string( forKey: .Log.level, as: Logger.Level.self, default: .info ) let serverName = reader.string( forKey: .HTTP.serverName, default: .Server.name ) let staticFilesPath = reader.string( forKey: .Path.staticFiles, default: .Path.staticResources ) return Application( router: router( staticFilesPath: staticFilesPath, logLevel: logLevel ), configuration: ApplicationConfiguration( reader: reader.scoped(to: "http") ), logger: logger( serverName: serverName, logLevel: logLevel ) ) } // MARK: - Helpers // Request context used by application private typealias AppRequestContext = BasicRequestContext /// Builds the application's logger. /// - Parameters: /// - serverName: the label applied to the logger. /// - logLevel: the minimum level the logger emits. /// - Returns: the configured logger. private func logger( serverName: String, logLevel: Logger.Level ) -> Logger { var logger = Logger(label: serverName) logger.logLevel = logLevel return logger } /// Builds the application's router. /// /// Registers the request-logging middleware, the not-found middleware that serves the error /// page, and the static file middleware that serves the contents of `staticFilesPath`, then /// adds the `RootController` routes that render the landing page. /// - Parameters: /// - staticFilesPath: the folder, relative to the working directory, the static files are served from. /// - logLevel: the level the request-logging middleware logs at. /// - Returns: the configured router. private func router( staticFilesPath: String, logLevel: Logger.Level ) -> Router { let router = Router(context: AppRequestContext.self) router.addMiddleware { LogRequestsMiddleware(logLevel) NotFoundMiddleware() FileMiddleware(staticFilesPath) } router.addRoutes(RootController().routes) return router }