Skip to content

Commit bd0b414

Browse files
authored
Support configurable paths prefixes for Connect routes (#40)
1 parent baa84c4 commit bd0b414

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

core/src/main/scala/org/ivovk/connect_rpc_scala/ConnectRouteBuilder.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import cats.effect.{Async, Resource}
55
import cats.implicits.*
66
import io.grpc.{ManagedChannelBuilder, ServerBuilder, ServerServiceDefinition}
77
import org.http4s.dsl.Http4sDsl
8-
import org.http4s.{HttpApp, HttpRoutes, Method}
8+
import org.http4s.{HttpApp, HttpRoutes, Method, Uri}
99
import org.ivovk.connect_rpc_scala.grpc.*
1010
import org.ivovk.connect_rpc_scala.http.*
1111
import org.ivovk.connect_rpc_scala.http.QueryParams.*
@@ -35,6 +35,7 @@ case class ConnectRouteBuilder[F[_] : Async] private(
3535
jsonPrinterConfigurator: Endo[Printer] = identity,
3636
serverConfigurator: Endo[ServerBuilder[_]] = identity,
3737
channelConfigurator: Endo[ManagedChannelBuilder[_]] = identity,
38+
pathPrefix: Uri.Path = Uri.Path.Root,
3839
executor: Executor = ExecutionContext.global,
3940
waitForShutdown: Duration = 5.seconds,
4041
treatTrailersAsHeaders: Boolean = true,
@@ -51,6 +52,9 @@ case class ConnectRouteBuilder[F[_] : Async] private(
5152
def withChannelConfigurator(method: Endo[ManagedChannelBuilder[_]]): ConnectRouteBuilder[F] =
5253
copy(channelConfigurator = method)
5354

55+
def withPathPrefix(path: Uri.Path): ConnectRouteBuilder[F] =
56+
copy(pathPrefix = path)
57+
5458
def withExecutor(executor: Executor): ConnectRouteBuilder[F] =
5559
copy(executor = executor)
5660

@@ -106,12 +110,12 @@ case class ConnectRouteBuilder[F[_] : Async] private(
106110
)
107111

108112
HttpRoutes.of[F] {
109-
case req@Method.GET -> Root / serviceName / methodName :? EncodingQP(contentType) +& MessageQP(message) =>
113+
case req@Method.GET -> pathPrefix / serviceName / methodName :? EncodingQP(contentType) +& MessageQP(message) =>
110114
val grpcMethod = MethodName(serviceName, methodName)
111115
val entity = RequestEntity[F](message, req.headers)
112116

113117
handler.handle(Method.GET, contentType.some, entity, grpcMethod)
114-
case req@Method.POST -> Root / serviceName / methodName =>
118+
case req@Method.POST -> pathPrefix / serviceName / methodName =>
115119
val grpcMethod = MethodName(serviceName, methodName)
116120
val contentType = req.contentType.map(_.mediaType)
117121
val entity = RequestEntity[F](req)

core/src/test/scala/org/ivovk/connect_rpc_scala/HttpTest.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,30 @@ class HttpTest extends AnyFunSuite, Matchers {
9090
.unsafeRunSync()
9191
}
9292

93+
test("support path prefixes") {
94+
val service = TestService.bindService(TestServiceImpl, ExecutionContext.global)
95+
96+
ConnectRouteBuilder.forService[IO](service)
97+
.withPathPrefix(Root / "connect")
98+
.build
99+
.flatMap { app =>
100+
val client = Client.fromHttpApp(app)
101+
102+
client.run(
103+
Request[IO](Method.POST, uri"/connect/org.ivovk.connect_rpc_scala.test.TestService/Add")
104+
.withEntity(""" { "a": 1, "b": 2} """)
105+
)
106+
}
107+
.use { response =>
108+
for {
109+
body <- response.as[String]
110+
status <- response.status.pure[IO]
111+
} yield {
112+
assert(body == """{"sum":3}""")
113+
assert(status == Status.Ok)
114+
}
115+
}
116+
.unsafeRunSync()
117+
}
118+
93119
}

0 commit comments

Comments
 (0)