mirror of
https://github.com/ReVanced/revanced-api.git
synced 2026-01-31 15:11:03 +00:00
feat: Add OpenAPI docs and cache to routes
This commit is contained in:
@@ -1,14 +1,22 @@
|
||||
package app.revanced.api.configuration.routes
|
||||
|
||||
import app.revanced.api.configuration.installCache
|
||||
import app.revanced.api.configuration.installNotarizedRoute
|
||||
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.schema.APIResponseAnnouncement
|
||||
import app.revanced.api.configuration.schema.APIResponseAnnouncementId
|
||||
import app.revanced.api.configuration.services.AnnouncementService
|
||||
import io.bkbn.kompendium.core.metadata.DeleteInfo
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.bkbn.kompendium.core.metadata.PatchInfo
|
||||
import io.bkbn.kompendium.core.metadata.PostInfo
|
||||
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
|
||||
import io.bkbn.kompendium.oas.payload.Parameter
|
||||
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.*
|
||||
@@ -20,49 +28,9 @@ import org.koin.ktor.ext.get as koinGet
|
||||
internal fun Route.announcementsRoute() = route("announcements") {
|
||||
val announcementService = koinGet<AnnouncementService>()
|
||||
|
||||
install(CachingHeaders) {
|
||||
options { _, _ ->
|
||||
CachingOptions(
|
||||
CacheControl.MaxAge(maxAgeSeconds = 1.minutes.inWholeSeconds.toInt()),
|
||||
)
|
||||
}
|
||||
}
|
||||
installCache(5.minutes)
|
||||
|
||||
rateLimit(RateLimitName("weak")) {
|
||||
route("{channel}/latest") {
|
||||
get("id") {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respondOrNotFound(announcementService.latestId(channel))
|
||||
}
|
||||
|
||||
get {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respondOrNotFound(announcementService.latest(channel))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
get("{channel}") {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respond(announcementService.all(channel))
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
route("latest") {
|
||||
get("id") {
|
||||
call.respondOrNotFound(announcementService.latestId())
|
||||
}
|
||||
|
||||
get {
|
||||
call.respondOrNotFound(announcementService.latest())
|
||||
}
|
||||
}
|
||||
}
|
||||
installAnnouncementsRouteDocumentation()
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
get {
|
||||
@@ -70,37 +38,333 @@ internal fun Route.announcementsRoute() = route("announcements") {
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
route("{channel}/latest") {
|
||||
installLatestChannelAnnouncementRouteDocumentation()
|
||||
|
||||
get {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respondOrNotFound(announcementService.latest(channel))
|
||||
}
|
||||
|
||||
route("id") {
|
||||
installLatestChannelAnnouncementIdRouteDocumentation()
|
||||
|
||||
get {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respondOrNotFound(announcementService.latestId(channel))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
route("{channel}") {
|
||||
installChannelAnnouncementsRouteDocumentation()
|
||||
|
||||
get {
|
||||
val channel: String by call.parameters
|
||||
|
||||
call.respond(announcementService.all(channel))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
route("latest") {
|
||||
installLatestAnnouncementRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respondOrNotFound(announcementService.latest())
|
||||
}
|
||||
|
||||
route("id") {
|
||||
installLatestAnnouncementIdRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respondOrNotFound(announcementService.latestId())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
authenticate("jwt") {
|
||||
post {
|
||||
announcementService.new(call.receive<APIAnnouncement>())
|
||||
post<APIAnnouncement> { announcement ->
|
||||
announcementService.new(announcement)
|
||||
}
|
||||
|
||||
post("{id}/archive") {
|
||||
val id: Int by call.parameters
|
||||
val archivedAt = call.receiveNullable<APIAnnouncementArchivedAt>()?.archivedAt
|
||||
route("{id}") {
|
||||
installAnnouncementIdRouteDocumentation()
|
||||
|
||||
announcementService.archive(id, archivedAt)
|
||||
}
|
||||
patch<APIAnnouncement> { announcement ->
|
||||
val id: Int by call.parameters
|
||||
|
||||
post("{id}/unarchive") {
|
||||
val id: Int by call.parameters
|
||||
announcementService.update(id, announcement)
|
||||
}
|
||||
|
||||
announcementService.unarchive(id)
|
||||
}
|
||||
delete {
|
||||
val id: Int by call.parameters
|
||||
|
||||
patch("{id}") {
|
||||
val id: Int by call.parameters
|
||||
val announcement = call.receive<APIAnnouncement>()
|
||||
announcementService.delete(id)
|
||||
}
|
||||
|
||||
announcementService.update(id, announcement)
|
||||
}
|
||||
route("archive") {
|
||||
installAnnouncementArchiveRouteDocumentation()
|
||||
|
||||
delete("{id}") {
|
||||
val id: Int by call.parameters
|
||||
post {
|
||||
val id: Int by call.parameters
|
||||
val archivedAt = call.receiveNullable<APIAnnouncementArchivedAt>()?.archivedAt
|
||||
|
||||
announcementService.delete(id)
|
||||
announcementService.archive(id, archivedAt)
|
||||
}
|
||||
}
|
||||
|
||||
route("unarchive") {
|
||||
installAnnouncementUnarchiveRouteDocumentation()
|
||||
|
||||
post {
|
||||
val id: Int by call.parameters
|
||||
|
||||
announcementService.unarchive(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installLatestAnnouncementRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the latest announcement")
|
||||
summary("Get latest announcement")
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
mediaTypes("application/json")
|
||||
description("The latest announcement")
|
||||
responseType<APIResponseAnnouncement>()
|
||||
}
|
||||
canRespond {
|
||||
responseCode(HttpStatusCode.NotFound)
|
||||
description("No announcement exists")
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installLatestAnnouncementIdRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the id of the latest announcement")
|
||||
summary("Get id of latest announcement")
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
mediaTypes("application/json")
|
||||
description("The id of the latest announcement")
|
||||
responseType<APIResponseAnnouncementId>()
|
||||
}
|
||||
canRespond {
|
||||
responseCode(HttpStatusCode.NotFound)
|
||||
description("No announcement exists")
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installChannelAnnouncementsRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "channel",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING,
|
||||
description = "The channel to get the announcements from",
|
||||
required = true,
|
||||
),
|
||||
)
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the announcements from a channel")
|
||||
summary("Get announcements from channel")
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
mediaTypes("application/json")
|
||||
description("The announcements in the channel")
|
||||
responseType<Set<APIResponseAnnouncement>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installAnnouncementArchiveRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.INT,
|
||||
description = "The id of the announcement to archive",
|
||||
required = true,
|
||||
),
|
||||
Parameter(
|
||||
name = "archivedAt",
|
||||
`in` = Parameter.Location.query,
|
||||
schema = TypeDefinition.STRING,
|
||||
description = "The date and time the announcement to be archived",
|
||||
required = false,
|
||||
),
|
||||
)
|
||||
|
||||
post = PostInfo.builder {
|
||||
description("Archive an announcement")
|
||||
summary("Archive announcement")
|
||||
response {
|
||||
description("When the announcement was archived")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installAnnouncementUnarchiveRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.INT,
|
||||
description = "The id of the announcement to unarchive",
|
||||
required = true,
|
||||
),
|
||||
)
|
||||
|
||||
post = PostInfo.builder {
|
||||
description("Unarchive an announcement")
|
||||
summary("Unarchive announcement")
|
||||
response {
|
||||
description("When announcement was unarchived")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installAnnouncementIdRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "id",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.INT,
|
||||
description = "The id of the announcement to update",
|
||||
required = true,
|
||||
),
|
||||
)
|
||||
|
||||
patch = PatchInfo.builder {
|
||||
description("Update an announcement")
|
||||
summary("Update announcement")
|
||||
request {
|
||||
requestType<APIAnnouncement>()
|
||||
description("The new announcement")
|
||||
}
|
||||
response {
|
||||
description("When announcement was updated")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
|
||||
delete = DeleteInfo.builder {
|
||||
description("Delete an announcement")
|
||||
summary("Delete announcement")
|
||||
response {
|
||||
description("When the announcement was deleted")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installAnnouncementsRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the announcements")
|
||||
summary("Get announcement")
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
mediaTypes("application/json")
|
||||
description("The announcements")
|
||||
responseType<Set<APIResponseAnnouncement>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installLatestChannelAnnouncementRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "channel",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING,
|
||||
description = "The channel to get the latest announcement from",
|
||||
required = true,
|
||||
),
|
||||
)
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the latest announcement from a channel")
|
||||
summary("Get latest channel announcement")
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
mediaTypes("application/json")
|
||||
description("The latest announcement in the channel")
|
||||
responseType<APIResponseAnnouncement>()
|
||||
}
|
||||
canRespond {
|
||||
responseCode(HttpStatusCode.NotFound)
|
||||
description("The channel does not exist")
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Route.installLatestChannelAnnouncementIdRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Announcements")
|
||||
|
||||
parameters = listOf(
|
||||
Parameter(
|
||||
name = "channel",
|
||||
`in` = Parameter.Location.path,
|
||||
schema = TypeDefinition.STRING,
|
||||
description = "The channel to get the latest announcement id from",
|
||||
required = true,
|
||||
),
|
||||
)
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the id of the latest announcement from a channel")
|
||||
summary("Get id of latest announcement from channel")
|
||||
response {
|
||||
responseCode(HttpStatusCode.OK)
|
||||
mediaTypes("application/json")
|
||||
description("The id of the latest announcement from the channel")
|
||||
responseType<APIResponseAnnouncementId>()
|
||||
}
|
||||
canRespond {
|
||||
responseCode(HttpStatusCode.NotFound)
|
||||
description("The channel does not exist")
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package app.revanced.api.configuration.routes
|
||||
|
||||
import app.revanced.api.configuration.installCache
|
||||
import app.revanced.api.configuration.installNoCache
|
||||
import app.revanced.api.configuration.installNotarizedRoute
|
||||
import app.revanced.api.configuration.respondOrNotFound
|
||||
import app.revanced.api.configuration.schema.APIContributable
|
||||
import app.revanced.api.configuration.schema.APIMember
|
||||
import app.revanced.api.configuration.schema.APIRateLimit
|
||||
import app.revanced.api.configuration.services.ApiService
|
||||
import app.revanced.api.configuration.services.AuthService
|
||||
import io.bkbn.kompendium.core.metadata.*
|
||||
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.*
|
||||
@@ -22,17 +26,19 @@ internal fun Route.rootRoute() {
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
authenticate("basic") {
|
||||
get("token") {
|
||||
call.respond(authService.newToken())
|
||||
route("token") {
|
||||
installTokenRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respond(authService.newToken())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
route("contributors") {
|
||||
install(CachingHeaders) {
|
||||
options { _, _ ->
|
||||
CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 1.days.inWholeSeconds.toInt()))
|
||||
}
|
||||
}
|
||||
installCache(1.days)
|
||||
|
||||
installContributorsRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respond(apiService.contributors())
|
||||
@@ -40,11 +46,9 @@ internal fun Route.rootRoute() {
|
||||
}
|
||||
|
||||
route("team") {
|
||||
install(CachingHeaders) {
|
||||
options { _, _ ->
|
||||
CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 1.days.inWholeSeconds.toInt()))
|
||||
}
|
||||
}
|
||||
installCache(1.days)
|
||||
|
||||
installTeamRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respond(apiService.team())
|
||||
@@ -53,20 +57,22 @@ internal fun Route.rootRoute() {
|
||||
}
|
||||
|
||||
route("ping") {
|
||||
install(CachingHeaders) {
|
||||
options { _, _ ->
|
||||
CachingOptions(CacheControl.NoCache(null))
|
||||
}
|
||||
}
|
||||
installNoCache()
|
||||
|
||||
handle {
|
||||
installPingRouteDocumentation()
|
||||
|
||||
head {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("weak")) {
|
||||
get("backend/rate_limit") {
|
||||
call.respondOrNotFound(apiService.rateLimit())
|
||||
route("backend/rate_limit") {
|
||||
installRateLimitRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respondOrNotFound(apiService.rateLimit())
|
||||
}
|
||||
}
|
||||
|
||||
staticResources("/", "/app/revanced/api/static") {
|
||||
@@ -75,3 +81,77 @@ internal fun Route.rootRoute() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installRateLimitRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the rate limit of the backend")
|
||||
summary("Get rate limit of backend")
|
||||
response {
|
||||
description("The rate limit of the backend")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<APIRateLimit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installPingRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
head = HeadInfo.builder {
|
||||
description("Ping the server")
|
||||
summary("Ping")
|
||||
response {
|
||||
description("The server is reachable")
|
||||
responseCode(HttpStatusCode.NoContent)
|
||||
responseType<Unit>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installTeamRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the list of team members")
|
||||
summary("Get team members")
|
||||
response {
|
||||
description("The list of team members")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<Set<APIMember>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installContributorsRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the list of contributors")
|
||||
summary("Get contributors")
|
||||
response {
|
||||
description("The list of contributors")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<Set<APIContributable>>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installTokenRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("API")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get a new authorization token")
|
||||
summary("Get authorization token")
|
||||
response {
|
||||
description("The authorization token")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<String>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package app.revanced.api.configuration.routes
|
||||
|
||||
import app.revanced.api.configuration.installNotarizedRoute
|
||||
import app.revanced.api.configuration.schema.APIRelease
|
||||
import app.revanced.api.configuration.schema.APIReleaseVersion
|
||||
import app.revanced.api.configuration.services.PatchesService
|
||||
import io.bkbn.kompendium.core.metadata.GetInfo
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.ratelimit.*
|
||||
@@ -12,20 +16,75 @@ internal fun Route.patchesRoute() = route("patches") {
|
||||
val patchesService = koinGet<PatchesService>()
|
||||
|
||||
route("latest") {
|
||||
installLatestPatchesRouteDocumentation()
|
||||
|
||||
rateLimit(RateLimitName("weak")) {
|
||||
get {
|
||||
call.respond(patchesService.latestRelease())
|
||||
}
|
||||
|
||||
get("version") {
|
||||
call.respond(patchesService.latestVersion())
|
||||
route("version") {
|
||||
installLatestPatchesVersionRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respond(patchesService.latestVersion())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rateLimit(RateLimitName("strong")) {
|
||||
get("list") {
|
||||
call.respondBytes(ContentType.Application.Json) { patchesService.list() }
|
||||
route("list") {
|
||||
installLatestPatchesListRouteDocumentation()
|
||||
|
||||
get {
|
||||
call.respondBytes(ContentType.Application.Json) { patchesService.list() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installLatestPatchesRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the latest patches release")
|
||||
summary("Get latest patches release")
|
||||
response {
|
||||
description("The latest patches release")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<APIRelease>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installLatestPatchesVersionRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the latest patches release version")
|
||||
summary("Get latest patches release version")
|
||||
response {
|
||||
description("The latest patches release version")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<APIReleaseVersion>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.installLatestPatchesListRouteDocumentation() = installNotarizedRoute {
|
||||
tags = setOf("Patches")
|
||||
|
||||
get = GetInfo.builder {
|
||||
description("Get the list of patches from the latest patches release")
|
||||
summary("Get list of patches from latest patches release")
|
||||
response {
|
||||
description("The list of patches")
|
||||
mediaTypes("application/json")
|
||||
responseCode(HttpStatusCode.OK)
|
||||
responseType<String>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user