6

每当我在我的 http4s 应用程序中遇到未知路由时,它都会返回 404 错误页面,其中包含Content-Type: text/plain和 body:

未找到

如何强制它始终将正文作为 JSON 返回Content-Type: application/json

{“未找到信息”}

我发现当我组装httpApp时,我可以映射它并“调整”响应:

val httpApp = Router.publicRoutes[F].orNotFound.map(ErrorTranslator.handle)

其中ErrorTranslator仅检测带有客户端错误状态代码和非application/json的 Content-Type的响应,然后将正文包装到 JSON 中:

object ErrorTranslator {

  val ContentType = "Content-Type"
  val ApplicationJson = "application/json"

  private def translate[F[_]: ConcurrentEffect: Sync](r: Response[F]): Response[F] =
    r.headers.get(CaseInsensitiveString(ContentType)).map(_.value) match {
      case Some(ApplicationJson) => r
      case _                     => r.withEntity(r.bodyAsText.map(ErrorView(_))) //wrap reponse body into enity
    }

  def handle[F[_]: ConcurrentEffect: Sync]: PartialFunction[Response[F], Response[F]] = {
    case Status.ClientError(r) => translate(r)
    case r                     => r
  }

}

它有效,但我想知道是否有一些不那么复杂的解决方案?

如果解决方案可以“翻译”其他错误,例如400 Bad request到 JSON,类似于呈现的代码,那也很棒。

4

2 回答 2

1

您还可以使用价值和mapF功能来制作它:

val jsonNotFound: Response[F] =
  Response(
    Status.NotFound,
    body = Stream("""{"error": "Not found"}""").through(utf8Encode),
    headers = Headers(`Content-Type`(MediaType.application.json) :: Nil)
  )
val routes: HttpRoutes[F] = routes.someRoutes().mapF(_.getOrElse(jsonNotFound))
于 2020-08-28T06:28:41.000 回答
1

我想您已经以类似的方式定义了您的路线,然后您可以添加一个默认案例语句

 HttpRoutes.of[IO] {
   case GET -> Root / "api" =>
        Ok()

   case _ -> Root =>
        // Your default route could be done like this
        Ok(io.circe.parser.parse("""{"message": "Not Found"}"""))
}
于 2020-01-06T14:58:55.990 回答