scala - Http4s解码器如何自定义无效字段的错误消息
问题描述
我有以下代码:
case req @ POST -> Root =>
req
.decode[UserCreateRequest] { decodedRequest =>
我的堆栈是 http4s + zio。
我为这个案例类添加了自定义解码器,其中有一行:
email <- Either.cond(StringValidator.isValidEmail(emailStr), Email(emailStr), DecodingFailure("email", c.history))
发布无效的 json 和无效的电子邮件返回给我:
HTTP/1.1 422 无法处理的实体内容类型:文本/纯文本;charset=UTF-8 日期:2021 年 1 月 19 日星期二 16:46:27 GMT 内容长度:29
请求正文无效。
响应代码:422(无法处理的实体);时间:681ms;内容长度:29字节
我想定制。在 http4s 代码中,我看到 InvalidMessageBodyFailure。但我在文档中找不到如何自定义此响应的任何信息。
有人可能已经试过了吗?
谢谢
编辑:
示例用户创建请求:
final case class UserCreateRequest(
email: Email
)
final case class Email(value: String) extends AnyVal
json请求:
{
"email": "myemail[at]gmail.com"
}
这可以使用这样的代码来实现:
(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))
但我想知道它是否可以通过一些已经完成但没有记录的http4s核心功能来简化:)
解决方案
您可以直接Status
从您的 API 返回。即你可以构造一个UnprocessableEntity
实例并使用这些withXXX
方法来改变响应。
假设一些结构:
final case class UserCreateRequest(isValid: Boolean)
你可以做:
case req @ POST -> Root / "foo" =>
for {
req <- req.decodeJson[UserCreateRequest]
resp <- if (req.isValid) Ok()
else UnprocessableEntity().map(_.withEntity(???).withAttribute(???))
} yield resp
推荐阅读
- javascript - amcharts 4世界地图工具提示中的交互式内容,不起作用
- qt - QML 添加两个输入并返回结果
- php - 在服务器上为多个用户运行 MySql
- dart - 如何使用 hero 获得相同的页面目标
- php - PHP 在类函数中使用 $_SESSION 变量作为默认值
- javascript - 使用javascript更改html元素的href
- watir - 使用 watir webdriver,无法按住一个点并移动到连接另一个点,因为没有相同的方法
- neo4j - 在 Neo4j 中合并不存在的节点并返回源节点
- javascript - 如何在 Android 的 GeoChart 中获取 arrayToDataTable()?
- database - 为什么 Postgres 更喜欢 seq 扫描而不是具有显式 where 条件的部分索引?