Декодер Http4s, как настроить сообщение об ошибке для недопустимых полей

У меня есть следующий код, например:

       case req @ POST -> Root =>
        req
          .decode[UserCreateRequest] { decodedRequest =>

мой стек http4s + zio.

Я добавил пользовательский декодер для этого класса case, где у меня есть строка:

      email <- Either.cond(StringValidator.isValidEmail(emailStr), Email(emailStr), DecodingFailure("email", c.history))

Публикация недопустимого json с неверным адресом электронной почты возвращает меня:

HTTP/1.1 422 Unprocessable Entity Content-Type: text/plain;charset=UTF-8 Дата: вторник, 19 января 2021 г., 16:46:27 GMT Content-Length: 29

Тело запроса недействительно.

Код ответа: 422 (необрабатываемый объект); Время: 681 мс; Длина содержимого: 29 байт.

который я хотел бы настроить. В коде http4s я вижу InvalidMessageBodyFailure. Но я не могу найти в документах информацию о том, как настроить этот ответ.

Кто-нибудь, может быть, пробовал это уже?

Благодарность

редактировать:

пример UserCreateRequest:

      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, которые уже сделаны, но не задокументированы :)

1 ответ

Вы можете напрямую вернуть 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
Другие вопросы по тегам