diff --git a/server/src/main/kotlin/at/mocode/server/Application.kt b/server/src/main/kotlin/at/mocode/server/Application.kt index bd884909..bcdb9e00 100644 --- a/server/src/main/kotlin/at/mocode/server/Application.kt +++ b/server/src/main/kotlin/at/mocode/server/Application.kt @@ -1,11 +1,22 @@ package at.mocode.server import at.mocode.server.plugins.configureDatabase +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpMethod +import io.ktor.http.HttpStatusCode +import io.ktor.serialization.kotlinx.json.json import io.ktor.server.application.* import io.ktor.server.netty.* +import io.ktor.server.plugins.calllogging.CallLogging +import io.ktor.server.plugins.contentnegotiation.ContentNegotiation +import io.ktor.server.plugins.cors.routing.CORS +import io.ktor.server.plugins.defaultheaders.DefaultHeaders +import io.ktor.server.plugins.statuspages.StatusPages import io.ktor.server.response.* import io.ktor.server.routing.* +import kotlinx.serialization.json.Json import org.slf4j.LoggerFactory +import org.slf4j.event.Level /** * Main entry point for the application. @@ -28,7 +39,7 @@ fun Application.module() { configureDatabase() // Configure plugins -// configurePlugins() + configurePlugins() // Configure routing configureRouting() @@ -39,84 +50,84 @@ fun Application.module() { /** * Configures all Ktor plugins for the application */ -//private fun Application.configurePlugins() { -// val log = LoggerFactory.getLogger("ApplicationPlugins") -// // Add default headers to all responses -// install(DefaultHeaders) { -// header("X-Engine", "Ktor") -// header("X-Content-Type-Options", "nosniff") -// } -// -// // Configure call logging -// install(CallLogging) { -// level = Level.INFO -// } -// -// // Configure content negotiation with JSON -// install(ContentNegotiation) { -// json(Json { -// prettyPrint = true -// isLenient = true -// ignoreUnknownKeys = true -// }) -// } -// -// // Configure CORS -// install(CORS) { -// // Default CORS configuration -// anyHost() -// allowMethod(HttpMethod.Options) -// allowMethod(HttpMethod.Get) -// allowMethod(HttpMethod.Post) -// allowMethod(HttpMethod.Put) -// allowMethod(HttpMethod.Delete) -// allowHeader(HttpHeaders.ContentType) -// allowHeader(HttpHeaders.Authorization) -// -// // Try to read from config to override defaults -// try { -// val appEnv = this@configurePlugins.environment.config -// if (appEnv.propertyOrNull("cors") != null) { -// val corsConfig = appEnv.config("cors") -// -// // Clear default anyHost if we have specific hosts -// if (corsConfig.propertyOrNull("allowedHosts") != null) { -// val hosts = corsConfig.property("allowedHosts").getList() -// if (hosts.isNotEmpty()) { -// hosts.forEach { host -> -// allowHost(host) -// } -// } -// } -// -// // Allow credentials if configured -// if (corsConfig.propertyOrNull("allowCredentials") != null) { -// allowCredentials = corsConfig.property("allowCredentials").getString().toBoolean() -// } -// } -// } catch (e: Exception) { -// // Log the error but continue with default configuration -// this@configurePlugins.log.warn("Failed to configure CORS from config, using defaults: ${e.message}") -// } -// } -// -// // Configure status pages for error handling -// install(StatusPages) { -// exception { call, cause -> -// call.respondText( -// text = "500: ${cause.message ?: "Internal Server Error"}", -// status = HttpStatusCode.InternalServerError -// ) -// } -// -// status(HttpStatusCode.NotFound) { call, _ -> -// call.respondText( -// text = "404: Page Not Found", -// status = HttpStatusCode.NotFound -// ) -// } -// } -//} +private fun Application.configurePlugins() { + val log = LoggerFactory.getLogger("ApplicationPlugins") + // Add default headers to all responses + install(DefaultHeaders) { + header("X-Engine", "Ktor") + header("X-Content-Type-Options", "nosniff") + } + + // Configure call logging + install(CallLogging) { + level = Level.INFO + } + + // Configure content negotiation with JSON + install(ContentNegotiation) { + json(Json { + prettyPrint = true + isLenient = true + ignoreUnknownKeys = true + }) + } + + // Configure CORS + install(CORS) { + // Default CORS configuration + anyHost() + allowMethod(HttpMethod.Options) + allowMethod(HttpMethod.Get) + allowMethod(HttpMethod.Post) + allowMethod(HttpMethod.Put) + allowMethod(HttpMethod.Delete) + allowHeader(HttpHeaders.ContentType) + allowHeader(HttpHeaders.Authorization) + + // Try to read from config to override defaults + try { + val appEnv = this@configurePlugins.environment.config + if (appEnv.propertyOrNull("cors") != null) { + val corsConfig = appEnv.config("cors") + + // Clear default anyHost if we have specific hosts + if (corsConfig.propertyOrNull("allowedHosts") != null) { + val hosts = corsConfig.property("allowedHosts").getList() + if (hosts.isNotEmpty()) { + hosts.forEach { host -> + allowHost(host) + } + } + } + + // Allow credentials if configured + if (corsConfig.propertyOrNull("allowCredentials") != null) { + allowCredentials = corsConfig.property("allowCredentials").getString().toBoolean() + } + } + } catch (e: Exception) { + // Log the error but continue with default configuration + this@configurePlugins.log.warn("Failed to configure CORS from config, using defaults: ${e.message}") + } + } + + // Configure status pages for error handling + install(StatusPages) { + exception { call, cause -> + call.respondText( + text = "500: ${cause.message ?: "Internal Server Error"}", + status = HttpStatusCode.InternalServerError + ) + } + + status(HttpStatusCode.NotFound) { call, _ -> + call.respondText( + text = "404: Page Not Found", + status = HttpStatusCode.NotFound + ) + } + } +} /** * Configures all routes for the application