add status endpoint

This commit is contained in:
Evgenii Alekseev 2022-01-17 16:57:32 +03:00
parent 78a00e2cab
commit 5d72852420
11 changed files with 118 additions and 16 deletions

View File

@ -1,3 +1,5 @@
organization := "me.arcanis"
name := "ffxivbis" name := "ffxivbis"
scalaVersion := "2.13.6" scalaVersion := "2.13.6"
@ -5,3 +7,4 @@ scalaVersion := "2.13.6"
scalacOptions ++= Seq("-deprecation", "-feature") scalacOptions ++= Seq("-deprecation", "-feature")
enablePlugins(JavaAppPackaging) enablePlugins(JavaAppPackaging)
coverageEnabled := true

View File

@ -1 +1 @@
sbt.version = 1.6.1 sbt.version = 1.5.8

View File

@ -11,6 +11,6 @@
<appender-ref ref="http" /> <appender-ref ref="http" />
</logger> </logger>
<logger name="org.flywaydb.core.internal" level="INFO" /> <logger name="org.flywaydb.core.internal" level="INFO" />
<logger name="com.zaxxer.hikari.pool.HikariPool" level="INFO" /> <logger name="com.zaxxer.hikari.pool" level="INFO" />
</configuration> </configuration>

View File

@ -13,8 +13,8 @@ import akka.http.scaladsl.server.Directive0
import akka.http.scaladsl.server.Directives.{extractClientIP, extractRequestContext, mapResponse, optionalHeaderValueByType} import akka.http.scaladsl.server.Directives.{extractClientIP, extractRequestContext, mapResponse, optionalHeaderValueByType}
import com.typesafe.scalalogging.Logger import com.typesafe.scalalogging.Logger
import java.time.{Instant, ZoneId}
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.{Instant, ZoneId}
import java.util.Locale import java.util.Locale
trait HttpLog { trait HttpLog {
@ -68,7 +68,7 @@ object HttpLog {
val httpLogDatetimeFormatter: DateTimeFormatter = val httpLogDatetimeFormatter: DateTimeFormatter =
DateTimeFormatter DateTimeFormatter
.ofPattern("dd/MMM/uuuu:HH:mm:ss xx ") .ofPattern("dd/MMM/uuuu:HH:mm:ss xx")
.withLocale(Locale.UK) .withLocale(Locale.UK)
.withZone(ZoneId.systemDefault()) .withZone(ZoneId.systemDefault())
} }

View File

@ -22,6 +22,7 @@ class Swagger(config: Config) extends SwaggerHttpService {
classOf[api.v1.LootEndpoint], classOf[api.v1.LootEndpoint],
classOf[api.v1.PartyEndpoint], classOf[api.v1.PartyEndpoint],
classOf[api.v1.PlayerEndpoint], classOf[api.v1.PlayerEndpoint],
classOf[api.v1.StatusEndpoint],
classOf[api.v1.TypesEndpoint], classOf[api.v1.TypesEndpoint],
classOf[api.v1.UserEndpoint] classOf[api.v1.UserEndpoint]
) )
@ -35,7 +36,7 @@ class Swagger(config: Config) extends SwaggerHttpService {
override val host: String = override val host: String =
if (config.hasPath("me.arcanis.ffxivbis.web.hostname")) config.getString("me.arcanis.ffxivbis.web.hostname") if (config.hasPath("me.arcanis.ffxivbis.web.hostname")) config.getString("me.arcanis.ffxivbis.web.hostname")
else s"${config.getString("me.arcanis.ffxivbis.web.host")}:${config.getString("me.arcanis.ffxivbis.web.port")}" else s"${config.getString("me.arcanis.ffxivbis.web.host")}:${config.getInt("me.arcanis.ffxivbis.web.port")}"
private val basicAuth = new SecurityScheme() private val basicAuth = new SecurityScheme()
.description("basic http auth") .description("basic http auth")

View File

@ -32,14 +32,15 @@ class RootApiV1Endpoint(
private val lootEndpoint = new LootEndpoint(storage, auth) private val lootEndpoint = new LootEndpoint(storage, auth)
private val partyEndpoint = new PartyEndpoint(storage, provider, auth) private val partyEndpoint = new PartyEndpoint(storage, provider, auth)
private val playerEndpoint = new PlayerEndpoint(storage, provider, auth) private val playerEndpoint = new PlayerEndpoint(storage, provider, auth)
private val statusEndpoint = new StatusEndpoint
private val typesEndpoint = new TypesEndpoint(config) private val typesEndpoint = new TypesEndpoint(config)
private val userEndpoint = new UserEndpoint(storage, auth) private val userEndpoint = new UserEndpoint(storage, auth)
def route: Route = def route: Route =
handleExceptions(exceptionHandler) { handleExceptions(exceptionHandler) {
handleRejections(rejectionHandler) { handleRejections(rejectionHandler) {
biSEndpoint.route ~ lootEndpoint.route ~ partyEndpoint.route ~ biSEndpoint.route ~ lootEndpoint.route ~ partyEndpoint.route ~ playerEndpoint.route ~
playerEndpoint.route ~ typesEndpoint.route ~ userEndpoint.route statusEndpoint.route ~ typesEndpoint.route ~ userEndpoint.route
} }
} }
} }

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2019-2022 Evgeniy Alekseev.
*
* This file is part of ffxivbis
* (see https://github.com/arcan1s/ffxivbis).
*
* License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause
*/
package me.arcanis.ffxivbis.http.api.v1
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.responses.ApiResponse
import jakarta.ws.rs._
import me.arcanis.ffxivbis.http.api.v1.json._
@Path("/api/v1")
class StatusEndpoint extends JsonSupport {
def route: Route = getServerStatus
@GET
@Path("status")
@Produces(value = Array("application/json"))
@Operation(
summary = "server status",
description = "Returns the server status descriptor",
responses = Array(
new ApiResponse(
responseCode = "200",
description = "Service status descriptor",
content = Array(new Content(schema = new Schema(implementation = classOf[StatusModel])))
),
new ApiResponse(
responseCode = "500",
description = "Internal server error",
content = Array(new Content(schema = new Schema(implementation = classOf[ErrorModel])))
),
),
tags = Array("status"),
)
def getServerStatus: Route =
path("status") {
get {
complete {
StatusModel(
version = Option(getClass.getPackage.getImplementationVersion),
)
}
}
}
}

View File

@ -52,5 +52,6 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
implicit val playerBiSLinkFormat: RootJsonFormat[PlayerBiSLinkModel] = jsonFormat2(PlayerBiSLinkModel.apply) implicit val playerBiSLinkFormat: RootJsonFormat[PlayerBiSLinkModel] = jsonFormat2(PlayerBiSLinkModel.apply)
implicit val playerIdWithCountersFormat: RootJsonFormat[PlayerIdWithCountersModel] = implicit val playerIdWithCountersFormat: RootJsonFormat[PlayerIdWithCountersModel] =
jsonFormat9(PlayerIdWithCountersModel.apply) jsonFormat9(PlayerIdWithCountersModel.apply)
implicit val statusFormat: RootJsonFormat[StatusModel] = jsonFormat1(StatusModel.apply)
implicit val userFormat: RootJsonFormat[UserModel] = jsonFormat4(UserModel.apply) implicit val userFormat: RootJsonFormat[UserModel] = jsonFormat4(UserModel.apply)
} }

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 2019-2022 Evgeniy Alekseev.
*
* This file is part of ffxivbis
* (see https://github.com/arcan1s/ffxivbis).
*
* License: 3-clause BSD, see https://opensource.org/licenses/BSD-3-Clause
*/
package me.arcanis.ffxivbis.http.api.v1.json
import io.swagger.v3.oas.annotations.media.Schema
case class StatusModel(@Schema(description = "server version") version: Option[String])

View File

@ -0,0 +1,29 @@
package me.arcanis.ffxivbis.http.api.v1
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import com.typesafe.config.Config
import me.arcanis.ffxivbis.Settings
import me.arcanis.ffxivbis.http.api.v1.json._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import scala.language.postfixOps
class StatusEndpointTest extends AnyWordSpecLike
with Matchers with ScalatestRouteTest with JsonSupport {
override val testConfig: Config = Settings.withRandomDatabase
private val route = new StatusEndpoint().route
"api v1 status endpoint" must {
"return server status" in {
Get("/status") ~> route ~> check {
status shouldEqual StatusCodes.OK
}
}
}
}