add morny's HttpStatus abstract and http:ping better

- add HttpStatus class which set the MornyNotFound REST error result etc.
- add fields `time` and `server` to http:ping result
- fix header errors
This commit is contained in:
A.C.Sukazyo Eyre 2024-04-19 15:27:47 +08:00
parent 2cbc75a2ca
commit f3db8f4457
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
8 changed files with 96 additions and 64 deletions

View File

@ -1,4 +1,4 @@
import sbt.*
//noinspection TypeAnnotation //noinspection TypeAnnotation
object MornyConfiguration { object MornyConfiguration {
@ -16,18 +16,18 @@ object MornyConfiguration {
val dependencies: Seq[ModuleID] = Seq( val dependencies: Seq[ModuleID] = Seq(
"com.github.spotbugs" % "spotbugs-annotations" % "4.8.2" % Compile, "com.github.spotbugs" % "spotbugs-annotations" % "4.8.4" % Compile,
"cc.sukazyo" % "messiva" % "0.2.0", "cc.sukazyo" % "messiva" % "0.2.0",
"cc.sukazyo" % "resource-tools" % "0.2.2", "cc.sukazyo" % "resource-tools" % "0.2.2",
"com.github.pengrad" % "java-telegram-bot-api" % "6.2.0", "com.github.pengrad" % "java-telegram-bot-api" % "6.2.0",
"org.http4s" %% "http4s-dsl" % "0.23.25", "org.http4s" %% "http4s-dsl" % "0.23.26",
"org.http4s" %% "http4s-circe" % "0.23.25", "org.http4s" %% "http4s-circe" % "0.23.26",
"org.http4s" %% "http4s-netty-server" % "0.5.12", "org.http4s" %% "http4s-netty-server" % "0.5.16",
"com.softwaremill.sttp.client3" %% "core" % "3.9.2", "com.softwaremill.sttp.client3" %% "core" % "3.9.5",
"com.softwaremill.sttp.client3" %% "okhttp-backend" % "3.9.2", "com.softwaremill.sttp.client3" %% "okhttp-backend" % "3.9.5",
"com.squareup.okhttp3" % "okhttp" % "4.12.0" % Runtime, "com.squareup.okhttp3" % "okhttp" % "4.12.0" % Runtime,
"org.typelevel" %% "case-insensitive" % "1.4.0", "org.typelevel" %% "case-insensitive" % "1.4.0",
@ -42,10 +42,10 @@ object MornyConfiguration {
// used for disable slf4j // used for disable slf4j
// due to the slf4j api have been used in the following libraries: // due to the slf4j api have been used in the following libraries:
// - cron-utils // - cron-utils
"org.slf4j" % "slf4j-nop" % "2.0.9" % Runtime, "org.slf4j" % "slf4j-nop" % "2.0.13" % Runtime,
"org.scalatest" %% "scalatest" % "3.2.17" % Test, "org.scalatest" %% "scalatest" % "3.2.18" % Test,
"org.scalatest" %% "scalatest-freespec" % "3.2.17" % Test, "org.scalatest" %% "scalatest-freespec" % "3.2.18" % Test,
// for test report // for test report
"com.vladsch.flexmark" % "flexmark" % "0.64.8" % Test, "com.vladsch.flexmark" % "flexmark" % "0.64.8" % Test,
"com.vladsch.flexmark" % "flexmark-profile-pegdown" % "0.64.8" % Test "com.vladsch.flexmark" % "flexmark-profile-pegdown" % "0.64.8" % Test

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -2,17 +2,14 @@ package cc.sukazyo.cono.morny.core.http
import cats.effect.IO import cats.effect.IO
import cc.sukazyo.cono.morny.core.http.api.HttpService4Api import cc.sukazyo.cono.morny.core.http.api.HttpService4Api
import cc.sukazyo.cono.morny.data.TelegramImages import org.http4s.HttpRoutes
import org.http4s.{HttpRoutes, MediaType}
import org.http4s.dsl.io.* import org.http4s.dsl.io.*
import org.http4s.headers.`Content-Type`
class ServiceUI extends HttpService4Api { class ServiceUI extends HttpService4Api {
override lazy val service: HttpRoutes[IO] = HttpRoutes.of[IO] { override lazy val service: HttpRoutes[IO] = HttpRoutes.of[IO] {
case GET -> Root => case GET -> Root =>
NotImplemented(TelegramImages.IMG_501.get) MornyNotImplemented()
.map(_.withContentType(`Content-Type`(MediaType.image.jpeg)))
} }
} }

View File

@ -1,32 +1,12 @@
package cc.sukazyo.cono.morny.core.http.api package cc.sukazyo.cono.morny.core.http.api
import cats.effect.IO import cats.effect.IO
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString import org.http4s.HttpRoutes
import org.http4s.{HttpRoutes, Response}
trait HttpService4Api { trait HttpService4Api extends HttpStatus {
lazy val service: HttpRoutes[IO] lazy val service: HttpRoutes[IO]
extension (response: Response[IO]) {
def setMornyInternalErrorHeader (e: Throwable): Response[IO] =
response.setMornyInternalErrorHeader(
e.getClass.getSimpleName,
e.getMessage,
e.toLogString
)
def setMornyInternalErrorHeader (
`Morny-Internal-Error-Type`: String,
`Morny-Internal-Error-Message`: String,
`Morny-Internal-Error-Detail`: String
): Response[IO] =
response.withHeaders(
"Morny-Internal-Error-Type" -> `Morny-Internal-Error-Type`,
"Morny-Internal-Error-Message" -> `Morny-Internal-Error-Message`,
"Morny-Internal-Error-Detail" -> `Morny-Internal-Error-Detail`,
)
}
} }
object HttpService4Api { object HttpService4Api {

View File

@ -0,0 +1,60 @@
package cc.sukazyo.cono.morny.core.http.api
import cats.effect.IO
import cc.sukazyo.cono.morny.data.TelegramImages
import cc.sukazyo.cono.morny.util.UseThrowable.toLogString
import org.http4s.{Header, MediaType, Response}
import org.http4s.dsl.io.*
import org.http4s.headers.`Content-Type`
trait HttpStatus {
private type ResponseT = Response[IO]
private type ResponseIO = IO[ResponseT]
extension (response: ResponseT) {
def setMornyInternalErrorHeader (e: Throwable): ResponseT =
response.setMornyInternalErrorHeader(
e.getClass.getSimpleName,
e.getMessage,
e.toLogString
)
def setMornyInternalErrorHeader (
`Morny-Internal-Error-Type`: String,
`Morny-Internal-Error-Message`: String,
`Morny-Internal-Error-Detail`: String
): ResponseT =
response
.putHeaders(
"Morny-Internal-Error-Type" -> `Morny-Internal-Error-Type`,
"Morny-Internal-Error-Message" -> `Morny-Internal-Error-Message`,
"Morny-Internal-Error-Detail" -> `Morny-Internal-Error-Detail`,
)
}
/** 400 Bad Request */
def MornyBadRequest (): ResponseIO =
BadRequest(TelegramImages.IMG_400.get)
.map(_.withContentType(`Content-Type`(MediaType.image.png)))
/** 404 Not Found */
def MornyNotFound (): ResponseIO =
NotFound(TelegramImages.IMG_404.get)
.map(_.withContentType(`Content-Type`(MediaType.image.png)))
/** 500 Internal Server Error */
def MornyInternalServerError (): ResponseIO =
InternalServerError(TelegramImages.IMG_500.get)
.map(_.withContentType(`Content-Type`(MediaType.image.png)))
/** 501 Not Implemented */
def MornyNotImplemented (): ResponseIO =
NotImplemented(TelegramImages.IMG_501.get)
.map(_.withContentType(`Content-Type`(MediaType.image.png)))
/** 523 Service Unavailable */
def MornyServiceUnavailable (): ResponseIO =
ServiceUnavailable(TelegramImages.IMG_523.get)
.map(_.withContentType(`Content-Type`(MediaType.image.png)))
}

View File

@ -2,14 +2,18 @@ package cc.sukazyo.cono.morny.core.http.services
import cats.effect.IO import cats.effect.IO
import cc.sukazyo.cono.morny.core.http.api.HttpService4Api import cc.sukazyo.cono.morny.core.http.api.HttpService4Api
import cc.sukazyo.cono.morny.core.MornySystem
import cc.sukazyo.cono.morny.util.CommonFormat
import org.http4s.{HttpRoutes, Response} import org.http4s.{HttpRoutes, Response}
import org.http4s.circe.jsonEncoder import org.http4s.circe.jsonEncoder
import org.http4s.dsl.io.* import org.http4s.dsl.io.*
class Ping extends HttpService4Api { class Ping extends HttpService4Api {
case class PingResult ( private case class PingResult (
pong: Boolean = true pong: Boolean = true,
time: String = CommonFormat.formatDate(System.currentTimeMillis(), 0),
server: String = MornySystem.VERSION_FULL,
) )
override lazy val service: HttpRoutes[IO] = HttpRoutes.of[IO] { override lazy val service: HttpRoutes[IO] = HttpRoutes.of[IO] {

View File

@ -30,6 +30,7 @@ object TelegramImages {
} }
val IMG_ABOUT: AssetsFileImage = AssetsFileImage("images/featured-image@0.5x.jpg") val IMG_ABOUT: AssetsFileImage = AssetsFileImage("images/featured-image@0.5x.jpg")
val IMG_400: AssetsFileImage = AssetsFileImage("images/http-sekai-400.png")
val IMG_404: AssetsFileImage = AssetsFileImage("images/http-sekai-404.png") val IMG_404: AssetsFileImage = AssetsFileImage("images/http-sekai-404.png")
val IMG_500: AssetsFileImage = AssetsFileImage("images/http-sekai-500.png") val IMG_500: AssetsFileImage = AssetsFileImage("images/http-sekai-500.png")
val IMG_501: AssetsFileImage = AssetsFileImage("images/http-sekai-501.png") val IMG_501: AssetsFileImage = AssetsFileImage("images/http-sekai-501.png")

View File

@ -3,14 +3,12 @@ package cc.sukazyo.cono.morny.stickers_get.http
import cats.effect.IO import cats.effect.IO
import cc.sukazyo.cono.morny.core.http.api.HttpService4Api import cc.sukazyo.cono.morny.core.http.api.HttpService4Api
import cc.sukazyo.cono.morny.core.MornyCoeur import cc.sukazyo.cono.morny.core.MornyCoeur
import cc.sukazyo.cono.morny.data.TelegramImages
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.File.getContent import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.File.getContent
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.execute import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Requests.execute
import com.pengrad.telegrambot.request.GetFile import com.pengrad.telegrambot.request.GetFile
import com.pengrad.telegrambot.TelegramBot import com.pengrad.telegrambot.TelegramBot
import org.http4s.{HttpRoutes, MediaType} import org.http4s.HttpRoutes
import org.http4s.dsl.io.* import org.http4s.dsl.io.*
import org.http4s.headers.`Content-Type`
import java.io.IOException import java.io.IOException
@ -28,34 +26,26 @@ class StickerService (using coeur: MornyCoeur) extends HttpService4Api {
Ok(file) Ok(file)
} catch { } catch {
case e: IOException => case e: IOException =>
ServiceUnavailable( MornyServiceUnavailable()
TelegramImages.IMG_523.get, .map(_.setMornyInternalErrorHeader(e))
`Content-Type`(MediaType.image.png),
).map(_.setMornyInternalErrorHeader(e))
} }
else else
NotFound( MornyNotFound()
TelegramImages.IMG_404.get, .map(_.setMornyInternalErrorHeader(
`Content-Type`(MediaType.image.png), "_telegram_api",
).map(_.setMornyInternalErrorHeader( response.errorCode.toString,
"_telegram_api", response.description,
response.errorCode.toString, ))
response.description,
))
} catch } catch
case io: IOException => case io: IOException =>
ServiceUnavailable( MornyServiceUnavailable()
TelegramImages.IMG_523.get, .map(_.setMornyInternalErrorHeader(io))
`Content-Type`(MediaType.image.png),
).map(_.setMornyInternalErrorHeader(io))
case e: Throwable => case e: Throwable =>
InternalServerError( MornyInternalServerError()
TelegramImages.IMG_500.get, .map(_.setMornyInternalErrorHeader(e))
`Content-Type`(MediaType.image.png),
).map(_.setMornyInternalErrorHeader(e))
case GET -> Root / "sticker" => case GET -> "sticker" /: rest =>
NotFound("not found") MornyBadRequest() // TODO: bad request
} }
} }