You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZIO HTTP 3中Endpoint接口的全局错误处理方案咨询

ZIO HTTP 3 通用Endpoint错误处理方案

下面提供三种实用的通用错误处理方案,避免每个Endpoint重复编写错误配置:

方案一:封装通用错误处理函数

写一个统一的函数,将业务逻辑返回的Task[A](即ZIO[Any, Throwable, A])转换成符合Endpoint要求的ZIO[Any, ZNothing, Response],集中处理所有通用错误:

import zio._
import zio.http._
import zio.json._

// 统一处理错误并转换为HTTP响应
def handleCommonErrors[R, A: JsonEncoder](zio: ZIO[R, Throwable, A]): ZIO[R, ZNothing, Response] =
  zio
    .map(data => Response.json(data.toJson)) // 统一序列化为JSON响应
    .catchAll {
      case e: IllegalArgumentException => 
        Response.badRequest(Json.obj("error" -> Json.string(e.getMessage)))
      case e: NoSuchElementException => 
        Response.notFound(Json.obj("error" -> Json.string(e.getMessage)))
      case _ => 
        Response.internalServerError(Json.obj("error" -> Json.string("服务器内部错误")))
    }

使用时只需用该函数包裹业务逻辑:

val dataEndpoint = Endpoint.get("/api/data").out[String]

dataEndpoint.implement { _ =>
  handleCommonErrors(fetchData()) // fetchData: Task[String] 为业务方法
}

方案二:全局错误处理中间件

利用ZIO HTTP的Middleware机制,在路由层面添加全局错误捕获,所有Endpoint都会自动应用该处理逻辑:

import zio.http._
import zio.json._

// 定义全局错误处理中间件
val globalErrorMiddleware: Middleware[Any, Nothing, Any, Response, Any, Response] =
  Middleware.catchAll {
    case e: IllegalArgumentException => 
      Response.badRequest(Json.obj("error" -> Json.string(e.getMessage)))
    case e: NoSuchElementException => 
      Response.notFound(Json.obj("error" -> Json.string(e.getMessage)))
    case _ => 
      Response.internalServerError(Json.obj("error" -> Json.string("服务器内部错误")))
  }

// 路由中应用中间件
val app = Routes(
  dataEndpoint.implement(_ => fetchData()),
  createEndpoint.implement(_ => createResource())
).withMiddleware(globalErrorMiddleware)

这种方式无需修改单个Endpoint的实现,所有未被捕获的错误都会被中间件拦截并转换为对应HTTP响应。

方案三:自定义通用Endpoint模板

预先定义包含统一错误输出配置的Endpoint模板,业务Endpoint基于模板扩展,避免重复编写.outError:

import zio.http._
import zio.json._

// 定义通用API错误类型
sealed trait ApiError
case class BadRequest(message: String) extends ApiError
case class NotFound(message: String) extends ApiError
case class ServerError(message: String) extends ApiError

// 为错误类型提供JSON编码器
object ApiError {
  implicit val encoder: JsonEncoder[ApiError] = DeriveJsonEncoder.gen[ApiError]
}

// 定义通用Endpoint模板,预先配置错误输出
def baseEndpoint(method: Method, path: Path): Endpoint[Any, ApiError, Unit, String, Nothing] =
  Endpoint(method, path)
    .out[String]
    .outError(
      Status.BadRequest -> json[BadRequest],
      Status.NotFound -> json[NotFound],
      Status.InternalServerError -> json[ServerError]
    )

// 基于模板创建业务Endpoint
val dataEndpoint = baseEndpoint(Method.GET, /"api"/"data")
val createEndpoint = baseEndpoint(Method.POST, /"api"/"data")

// 实现时只需将业务异常映射为ApiError
dataEndpoint.implement { _ =>
  fetchData()
    .mapError {
      case e: IllegalArgumentException => BadRequest(e.getMessage)
      case e: NoSuchElementException => NotFound(e.getMessage)
      case _ => ServerError("服务器内部错误")
    }
}

该方案适合需要明确API错误契约的场景,让所有Endpoint的错误输出格式保持一致。


内容的提问来源于stack exchange,提问作者user22087954

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:16:11