Reputation: 2699
I have following code like:
case req @ POST -> Root =>
req
.decode[UserCreateRequest] { decodedRequest =>
my stack is http4s + zio.
Ive added custom decoder for this case class where I have a line:
email <- Either.cond(StringValidator.isValidEmail(emailStr), Email(emailStr), DecodingFailure("email", c.history))
Posting invalid json, with invalid email returns me:
HTTP/1.1 422 Unprocessable Entity Content-Type: text/plain; charset=UTF-8 Date: Tue, 19 Jan 2021 16:46:27 GMT Content-Length: 29
The request body was invalid.
Response code: 422 (Unprocessable Entity); Time: 681ms; Content length: 29 bytes
which I would like to customize. In http4s code I see InvalidMessageBodyFailure. But I can not find in docs any info how to customize this response.
Any one maybe tried this already ?
thanks
edit:
sample UserCreateRequest:
final case class UserCreateRequest(
email: Email
)
final case class Email(value: String) extends AnyVal
json request:
{
"email": "myemail[at]gmail.com"
}
this can be achieved using such code:
(for {
decodedJson <- req.asJson.mapError { decodingError =>
HttpDecodingError(cause = decodingError.getMessage)
}
decodedRequest <- Task.fromEither(decodedJson.as[UserCreateRequest]).mapError { decodingError =>
HttpDecodingError(cause = decodingError.getMessage)
}
response <- UserService
.createNewUser(
decodedRequest.email
)
.bimap(
error => HttpGenericError(msg = error.msg, cause = error.cause.toString),
u => UserResponse(u.email.value)
)
} yield response).foldM((error: HttpError) => BadRequest(error), u => Ok(u))
but I wonder if it can be simplified, by some http4s core features, which are done already but not documented :)
Upvotes: 2
Views: 1191
Reputation: 149558
You can directly return the Status
from your API. i.e. you could construct an UnprocessableEntity
instance and use the withXXX
methods to alter the response.
Assuming some structure:
final case class UserCreateRequest(isValid: Boolean)
You can do:
case req @ POST -> Root / "foo" =>
for {
req <- req.decodeJson[UserCreateRequest]
resp <- if (req.isValid) Ok()
else UnprocessableEntity().map(_.withEntity(???).withAttribute(???))
} yield resp
Upvotes: 2