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

如何在http4s 0.15.16版本中合并多个HttpService

http4s 0.15.16 合并多个HttpService的替代方案

问题背景

我维护一个基于http4s 0.8版本的遗留系统,正在增量升级到0.15.16版本。之前版本中可以用service1 orElse service2的方式合并多个HttpService,但升级后orElse方法已不可用,不清楚如何替换实现。

原有代码示例:

object Test {
    val db = MySQLAdapter(url = "jdbc:mysql:///test?useSSL=false", user = "service", password = "")
    val userDao = UserDao(db)
}

object HealthApi extends ResponseCodec with BooleanCodec {
    
    def service =
        HttpService {
            case GET -> Root / "ping" => true
        }
    
}
object Main extends ServerApp with ResponseCodec with TimestampCodec {
    def service: HttpService = HttpService {
        case GET -> Root / "hello" / name => s"Hello $name"
        case GET -> Root / "user" => Test.userDao.testUser("admin@exam.com")
    }
    def server(args: List[String]): Task[Server] =
        BlazeBuilder
            .withNio2(true)
            .bindHttp(8080)
            .mountService(service, "/api")
            .start
}

解决方案

在http4s 0.15.x版本中,合并HttpService可以通过以下两种方式实现:

1. 使用combineK合并独立服务实例

http4s 0.15的HttpService基于cats的Kleisli类型,可通过cats的combineK方法实现服务合并,效果等价于旧版本的orElse。

步骤:

  • 导入cats的combineK语法
  • 调用combineK链式合并多个服务

修改后的Main示例:

import cats.syntax.combineK._

object Main extends ServerApp with ResponseCodec with TimestampCodec {
    def mainService: HttpService = HttpService {
        case GET -> Root / "hello" / name => s"Hello $name"
        case GET -> Root / "user" => Test.userDao.testUser("admin@exam.com")
    }

    // 合并Main服务与HealthApi服务
    val combinedService = mainService combineK HealthApi.service

    def server(args: List[String]): Task[Server] =
        BlazeBuilder
            .withNio2(true)
            .bindHttp(8080)
            .mountService(combinedService, "/api")
            .start
}

如果有更多服务,继续链式调用即可:service1 combineK service2 combineK service3

2. 直接合并路由块

如果不需要保持服务的独立性,也可以将多个路由逻辑直接合并到同一个HttpService定义中:

def service: HttpService = HttpService {
    // Main的路由逻辑
    case GET -> Root / "hello" / name => s"Hello $name"
    case GET -> Root / "user" => Test.userDao.testUser("admin@exam.com")
} <+> HttpService {
    // HealthApi的路由逻辑
    case GET -> Root / "ping" => true
}

注:<+>是combineK的运算符别名,效果完全一致。

依赖说明

确保项目依赖中包含cats-core(http4s 0.15通常会默认依赖,但如果缺失需要手动添加)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:39:19