From 205bcde77aad90e0eb49fc25961399f1e37698bb Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 8 Jun 2024 03:41:48 +0200 Subject: [PATCH] feat: Setup cors and cache --- configuration.example.toml | 1 + configuration.toml | 1 + .../revanced/api/command/StartAPICommand.kt | 2 +- .../app/revanced/api/configuration/HTTP.kt | 22 ++++------ .../app/revanced/api/configuration/Routing.kt | 12 ++++++ .../repository/ConfigurationRepository.kt | 1 + .../api/configuration/routes/Announcements.kt | 13 ++++++ .../api/configuration/routes/ApiRoute.kt | 40 +++++++++++++++---- 8 files changed, 69 insertions(+), 23 deletions(-) diff --git a/configuration.example.toml b/configuration.example.toml index dcef633..e969f57 100644 --- a/configuration.example.toml +++ b/configuration.example.toml @@ -12,3 +12,4 @@ contributors-repositories = [ "revanced-manager", ] api-version = 1 +host = "*.revanced.app" diff --git a/configuration.toml b/configuration.toml index dcef633..044b6e4 100644 --- a/configuration.toml +++ b/configuration.toml @@ -12,3 +12,4 @@ contributors-repositories = [ "revanced-manager", ] api-version = 1 +host = "*.revanced.app" \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/api/command/StartAPICommand.kt b/src/main/kotlin/app/revanced/api/command/StartAPICommand.kt index 826a1eb..7131be4 100644 --- a/src/main/kotlin/app/revanced/api/command/StartAPICommand.kt +++ b/src/main/kotlin/app/revanced/api/command/StartAPICommand.kt @@ -39,7 +39,7 @@ internal object StartAPICommand : Runnable { override fun run() { embeddedServer(Jetty, port, host) { configureDependencies(configFile) - configureHTTP(allowedHost = host) + configureHTTP() configureSerialization() configureSecurity() configureRouting() diff --git a/src/main/kotlin/app/revanced/api/configuration/HTTP.kt b/src/main/kotlin/app/revanced/api/configuration/HTTP.kt index d61350d..09811a1 100644 --- a/src/main/kotlin/app/revanced/api/configuration/HTTP.kt +++ b/src/main/kotlin/app/revanced/api/configuration/HTTP.kt @@ -1,28 +1,20 @@ package app.revanced.api.configuration -import io.ktor.http.* -import io.ktor.http.content.* +import app.revanced.api.configuration.repository.ConfigurationRepository import io.ktor.server.application.* import io.ktor.server.plugins.* -import io.ktor.server.plugins.cachingheaders.* import io.ktor.server.plugins.cors.routing.* import io.ktor.server.plugins.ratelimit.* +import org.koin.ktor.ext.get import kotlin.time.Duration.Companion.minutes -fun Application.configureHTTP( - allowedHost: String, -) { +fun Application.configureHTTP() { + val configurationRepository = get() + install(CORS) { - allowMethod(HttpMethod.Options) - allowMethod(HttpMethod.Put) - allowMethod(HttpMethod.Delete) - allowMethod(HttpMethod.Patch) - allowHeader(HttpHeaders.Authorization) - allowHost(allowedHost) - } - install(CachingHeaders) { - options { _, _ -> CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 5.minutes.inWholeSeconds.toInt())) } + allowHost(host = configurationRepository.host) } + install(RateLimit) { register(RateLimitName("weak")) { rateLimiter(limit = 30, refillPeriod = 2.minutes) diff --git a/src/main/kotlin/app/revanced/api/configuration/Routing.kt b/src/main/kotlin/app/revanced/api/configuration/Routing.kt index 1aee522..d6dcff8 100644 --- a/src/main/kotlin/app/revanced/api/configuration/Routing.kt +++ b/src/main/kotlin/app/revanced/api/configuration/Routing.kt @@ -5,13 +5,25 @@ import app.revanced.api.configuration.routes.announcementsRoute import app.revanced.api.configuration.routes.oldApiRoute import app.revanced.api.configuration.routes.patchesRoute import app.revanced.api.configuration.routes.rootRoute +import io.ktor.http.* +import io.ktor.http.content.* import io.ktor.server.application.* +import io.ktor.server.plugins.cachingheaders.* import io.ktor.server.routing.* import org.koin.ktor.ext.get +import kotlin.time.Duration.Companion.minutes internal fun Application.configureRouting() = routing { val configuration = get() + install(CachingHeaders) { + options { _, _ -> + CachingOptions( + CacheControl.MaxAge(maxAgeSeconds = 5.minutes.inWholeSeconds.toInt()), + ) + } + } + route("/v${configuration.apiVersion}") { rootRoute() patchesRoute() diff --git a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt index 3d5f28c..a7a3702 100644 --- a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt +++ b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt @@ -14,4 +14,5 @@ internal class ConfigurationRepository( val contributorsRepositoryNames: Set, @SerialName("api-version") val apiVersion: Int = 1, + val host: String, ) diff --git a/src/main/kotlin/app/revanced/api/configuration/routes/Announcements.kt b/src/main/kotlin/app/revanced/api/configuration/routes/Announcements.kt index 7630b6b..984eb17 100644 --- a/src/main/kotlin/app/revanced/api/configuration/routes/Announcements.kt +++ b/src/main/kotlin/app/revanced/api/configuration/routes/Announcements.kt @@ -4,18 +4,30 @@ import app.revanced.api.configuration.respondOrNotFound import app.revanced.api.configuration.schema.APIAnnouncement import app.revanced.api.configuration.schema.APIAnnouncementArchivedAt import app.revanced.api.configuration.services.AnnouncementService +import io.ktor.http.* +import io.ktor.http.content.* import io.ktor.server.application.* import io.ktor.server.auth.* +import io.ktor.server.plugins.cachingheaders.* import io.ktor.server.plugins.ratelimit.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.server.util.* +import kotlin.time.Duration.Companion.minutes import org.koin.ktor.ext.get as koinGet internal fun Route.announcementsRoute() = route("announcements") { val announcementService = koinGet() + install(CachingHeaders) { + options { _, _ -> + CachingOptions( + CacheControl.MaxAge(maxAgeSeconds = 1.minutes.inWholeSeconds.toInt()), + ) + } + } + rateLimit(RateLimitName("weak")) { route("{channel}/latest") { get("id") { @@ -39,6 +51,7 @@ internal fun Route.announcementsRoute() = route("announcements") { call.respond(announcementService.all(channel)) } } + rateLimit(RateLimitName("strong")) { route("latest") { get("id") { diff --git a/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt b/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt index 3271b81..2b20b0b 100644 --- a/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt +++ b/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt @@ -4,17 +4,21 @@ import app.revanced.api.configuration.respondOrNotFound import app.revanced.api.configuration.services.ApiService import app.revanced.api.configuration.services.AuthService import io.ktor.http.* +import io.ktor.http.content.CachingOptions import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.http.content.* +import io.ktor.server.plugins.cachingheaders.* +import io.ktor.server.plugins.cors.routing.* import io.ktor.server.plugins.ratelimit.* import io.ktor.server.response.* import io.ktor.server.routing.* -import org.koin.ktor.ext.get +import kotlin.time.Duration.Companion.days +import org.koin.ktor.ext.get as koinGet internal fun Route.rootRoute() { - val apiService = get() - val authService = get() + val apiService = koinGet() + val authService = koinGet() rateLimit(RateLimitName("strong")) { authenticate("basic") { @@ -23,16 +27,38 @@ internal fun Route.rootRoute() { } } - get("contributors") { - call.respond(apiService.contributors()) + route("contributors") { + install(CachingHeaders) { + options { _, _ -> + CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 1.days.inWholeSeconds.toInt())) + } + } + + get { + call.respond(apiService.contributors()) + } } - get("team") { - call.respond(apiService.team()) + route("team") { + install(CachingHeaders) { + options { _, _ -> + CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 1.days.inWholeSeconds.toInt())) + } + } + + get { + call.respond(apiService.team()) + } } } route("ping") { + install(CachingHeaders) { + options { _, _ -> + CachingOptions(CacheControl.NoCache(null)) + } + } + handle { call.respond(HttpStatusCode.NoContent) }