Skip to content

Commit 966b10b

Browse files
committed
update Api Errors adding support for Found (http 302) and ExtendedErrorInfo trait
1 parent 2e09ac0 commit 966b10b

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ ThisBuild / organization := "app.softnetwork"
88

99
name := "generic-persistence-api"
1010

11-
ThisBuild / version := "0.4.1"
11+
ThisBuild / version := "0.4.2"
1212

1313
ThisBuild / scalaVersion := "2.12.18"
1414

server/src/main/scala/app/softnetwork/api/server/ApiErrors.scala

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package app.softnetwork.api.server
22

33
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
4-
import akka.http.scaladsl.server.Directives.complete
4+
import akka.http.scaladsl.server.Directives._
55
import akka.http.scaladsl.server.Route
66
import app.softnetwork.serialization.commonFormats
77
import org.json4s.Formats
8-
import sttp.model.StatusCode
8+
import sttp.model.{HeaderNames, StatusCode, Uri}
99
import sttp.tapir.EndpointOutput.OneOf
1010
import sttp.tapir.server.PartialServerEndpointWithSecurityOutput
1111
import sttp.tapir._
@@ -21,6 +21,8 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
2121
val message: String
2222
}
2323

24+
trait ExtendedErrorInfo extends ErrorInfo
25+
2426
/** Represents http 404. */
2527
case class NotFound(message: String) extends ErrorInfo
2628

@@ -42,6 +44,32 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
4244
/** Represents http 500. */
4345
case class InternalServerError(message: String) extends ErrorInfo
4446

47+
/** Represents http 302. */
48+
case class Found(uri: Uri) extends ErrorInfo {
49+
override val message: String = s"Found $uri"
50+
override def toString: String = uri.toString()
51+
}
52+
53+
object Found {
54+
def apply(uri: String): Option[Found] = Uri.parse(uri).toOption.map(Found(_))
55+
}
56+
57+
implicit val foundCodec: Codec[String, Found, CodecFormat.TextPlain] =
58+
Codec.string.mapDecode(s =>
59+
Uri.parse(s) match {
60+
case Right(r) => DecodeResult.Value(Found(r))
61+
case Left(l) => DecodeResult.Error(s, new IllegalArgumentException(l))
62+
}
63+
)(_.toString())
64+
65+
implicit def leftFoundCodec[T]: Codec[String, Left[Found, T], CodecFormat.TextPlain] =
66+
Codec.string.mapDecode(s =>
67+
Uri.parse(s) match {
68+
case Right(r) => DecodeResult.Value(Left[Found, T](Found(r)))
69+
case Left(l) => DecodeResult.Error(s, new IllegalArgumentException(l))
70+
}
71+
)(_.left.get.toString())
72+
4573
implicit def apiError2Route(apiError: ErrorInfo)(implicit formats: Formats): Route =
4674
apiError match {
4775
case r: BadRequest => complete(HttpResponse(StatusCodes.BadRequest, entity = r))
@@ -51,6 +79,7 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
5179
complete(HttpResponse(StatusCodes.InternalServerError, entity = r))
5280
case r: NotFound => complete(HttpResponse(StatusCodes.NotFound, entity = r))
5381
case r: Unauthorized => complete(HttpResponse(StatusCodes.Unauthorized, entity = r))
82+
case r: Found => redirect(r.toString, StatusCodes.Found)
5483
case r: ErrorMessage => complete(HttpResponse(StatusCodes.OK, entity = r))
5584
}
5685

@@ -80,6 +109,12 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
80109
.and(jsonBody[ApiErrors.NotFound].description("When something not found"))
81110
)
82111

112+
val foundVariant: EndpointOutput.OneOfVariant[ApiErrors.Found] =
113+
oneOfVariant(
114+
statusCode(StatusCode.Found)
115+
.and(header[ApiErrors.Found](HeaderNames.Location).description("Redirect address"))
116+
)
117+
83118
val badRequestVariant: EndpointOutput.OneOfVariant[ApiErrors.BadRequest] =
84119
oneOfVariant(
85120
statusCode(StatusCode.BadRequest)
@@ -107,6 +142,7 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
107142
forbiddenVariant,
108143
unauthorizedVariant,
109144
notFoundVariant,
145+
foundVariant,
110146
badRequestVariant,
111147
internalServerErrorVariant,
112148
// default case below.
@@ -139,6 +175,12 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
139175
) { case Left(ApiErrors.NotFound(_)) =>
140176
true
141177
},
178+
oneOfVariantValueMatcher(
179+
StatusCode.Found,
180+
header[Left[ApiErrors.Found, T]]("Location").description("Redirect address")
181+
) { case Left(ApiErrors.Found(_)) =>
182+
true
183+
},
142184
oneOfVariantValueMatcher(
143185
StatusCode.BadRequest,
144186
jsonBody[Left[ApiErrors.BadRequest, T]].description("Bad request")
@@ -185,6 +227,7 @@ object ApiErrors extends SchemaDerivation with TapirJson4s {
185227
forbiddenVariant,
186228
unauthorizedVariant,
187229
notFoundVariant,
230+
foundVariant,
188231
badRequestVariant,
189232
internalServerErrorVariant,
190233
defaultErrorVariant

0 commit comments

Comments
 (0)