Skip to content

Commit 3ddc3e0

Browse files
authored
Allow prepending input path to HttpInterpreter generated Tapir endpoints (#2188)
1 parent 8e6950b commit 3ddc3e0

File tree

3 files changed

+88
-5
lines changed

3 files changed

+88
-5
lines changed

interop/tapir/src/main/scala/caliban/interop/tapir/HttpInterpreter.scala

+35-5
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,24 @@ sealed trait HttpInterpreter[-R, E] { self =>
1919
serverRequest: ServerRequest
2020
)(implicit streamConstructor: StreamConstructor[BS]): ZIO[R, TapirResponse, CalibanResponse[BS]]
2121

22-
def serverEndpoints[R1 <: R, S](stream: Streams[S])(implicit
23-
streamConstructor: StreamConstructor[stream.BinaryStream]
24-
): List[CalibanEndpoint[R1, stream.BinaryStream, S]] = {
22+
def serverEndpoints[R1 <: R, S](streams: Streams[S])(implicit
23+
streamConstructor: StreamConstructor[streams.BinaryStream]
24+
): List[CalibanEndpoint[R1, streams.BinaryStream, S]] = {
2525
def logic(
2626
request: (GraphQLRequest, ServerRequest)
27-
): RIO[R1, Either[TapirResponse, CalibanResponse[stream.BinaryStream]]] = {
27+
): RIO[R1, Either[TapirResponse, CalibanResponse[streams.BinaryStream]]] = {
2828
val (graphQLRequest, serverRequest) = request
2929
executeRequest(graphQLRequest, serverRequest).either
3030
}
31-
endpoints[S](stream).map(_.serverLogic(logic(_)))
31+
endpoints[S](streams).map(_.serverLogic(logic(_)))
3232
}
3333

3434
def intercept[R1](interceptor: Interceptor[R1, R]): HttpInterpreter[R1, E] =
3535
HttpInterpreter.Intercepted(self, interceptor)
3636

37+
def prependPath(path: List[String]): HttpInterpreter[R, E] =
38+
HttpInterpreter.Prepended(self, path)
39+
3740
def configure[R1](configurator: Configurator[R1]): HttpInterpreter[R & R1, E] =
3841
intercept[R & R1](ZLayer.scopedEnvironment[R & R1 & ServerRequest](configurator *> ZIO.environment[R]))
3942
}
@@ -63,6 +66,33 @@ object HttpInterpreter {
6366
}
6467
}
6568

69+
private case class Prepended[R, E](
70+
interpreter: HttpInterpreter[R, E],
71+
path: List[String]
72+
) extends HttpInterpreter[R, E] {
73+
override def endpoints[S](
74+
streams: Streams[S]
75+
): List[
76+
PublicEndpoint[(GraphQLRequest, ServerRequest), TapirResponse, CalibanResponse[streams.BinaryStream], S]
77+
] = {
78+
val endpoints = interpreter.endpoints(streams)
79+
if (path.nonEmpty) {
80+
val p: List[EndpointInput[Unit]] = path.map(stringToPath)
81+
val fixedPath: EndpointInput[Unit] = p.tail.foldLeft(p.head)(_ / _)
82+
83+
endpoints.map(_.prependIn(fixedPath))
84+
} else {
85+
endpoints
86+
}
87+
}
88+
89+
def executeRequest[BS](
90+
graphQLRequest: GraphQLRequest,
91+
serverRequest: ServerRequest
92+
)(implicit streamConstructor: StreamConstructor[BS]): ZIO[R, TapirResponse, CalibanResponse[BS]] =
93+
interpreter.executeRequest(graphQLRequest, serverRequest)
94+
}
95+
6696
private case class Intercepted[R1, R, E](
6797
interpreter: HttpInterpreter[R, E],
6898
layer: ZLayer[R1 & ServerRequest, TapirResponse, R]

interop/tapir/src/main/scala/caliban/interop/tapir/HttpUploadInterpreter.scala

+28
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ sealed trait HttpUploadInterpreter[-R, E] { self =>
8484
def intercept[R1](interceptor: Interceptor[R1, R]): HttpUploadInterpreter[R1, E] =
8585
HttpUploadInterpreter.Intercepted(self, interceptor)
8686

87+
def prependPath(path: List[String]): HttpUploadInterpreter[R, E] =
88+
HttpUploadInterpreter.Prepended(self, path)
89+
8790
def configure[R1](configurator: Configurator[R1]): HttpUploadInterpreter[R & R1, E] =
8891
intercept[R & R1](ZLayer.scopedEnvironment[R & R1 & ServerRequest](configurator *> ZIO.environment[R]))
8992
}
@@ -123,6 +126,31 @@ object HttpUploadInterpreter {
123126
interpreter.executeRequest(graphQLRequest, serverRequest).provideSome[R1](ZLayer.succeed(serverRequest), layer)
124127
}
125128

129+
private case class Prepended[R, E](
130+
interpreter: HttpUploadInterpreter[R, E],
131+
path: List[String]
132+
) extends HttpUploadInterpreter[R, E] {
133+
override def endpoint[S](
134+
streams: Streams[S]
135+
): PublicEndpoint[UploadRequest, TapirResponse, CalibanResponse[streams.BinaryStream], S] = {
136+
val endpoints = interpreter.endpoint(streams)
137+
if (path.nonEmpty) {
138+
val p: List[EndpointInput[Unit]] = path.map(stringToPath)
139+
val fixedPath: EndpointInput[Unit] = p.tail.foldLeft(p.head)(_ / _)
140+
141+
endpoints.prependIn(fixedPath)
142+
} else {
143+
endpoints
144+
}
145+
}
146+
147+
def executeRequest[BS](
148+
graphQLRequest: GraphQLRequest,
149+
serverRequest: ServerRequest
150+
)(implicit streamConstructor: StreamConstructor[BS]): ZIO[R, TapirResponse, CalibanResponse[BS]] =
151+
interpreter.executeRequest(graphQLRequest, serverRequest)
152+
}
153+
126154
def apply[R, E](
127155
interpreter: GraphQLInterpreter[R, E]
128156
)(implicit responseValueCodec: JsonCodec[ResponseValue]): HttpUploadInterpreter[R, E] =

interop/tapir/src/main/scala/caliban/interop/tapir/WebSocketInterpreter.scala

+25
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ sealed trait WebSocketInterpreter[-R, E] { self =>
2828
def intercept[R1](interceptor: Interceptor[R1, R]): WebSocketInterpreter[R1, E] =
2929
WebSocketInterpreter.Intercepted(self, interceptor)
3030

31+
def prependPath(path: List[String]): WebSocketInterpreter[R, E] =
32+
WebSocketInterpreter.Prepended(self, path)
33+
3134
def configure[R1](configurator: Configurator[R1]): WebSocketInterpreter[R & R1, E] =
3235
intercept[R & R1](ZLayer.scopedEnvironment[R & R1 & ServerRequest](configurator *> ZIO.environment[R]))
3336
}
@@ -74,6 +77,28 @@ object WebSocketInterpreter {
7477
.catchAll(ZIO.left(_))
7578
}
7679

80+
private case class Prepended[R, E](
81+
interpreter: WebSocketInterpreter[R, E],
82+
path: List[String]
83+
) extends WebSocketInterpreter[R, E] {
84+
val endpoint: PublicEndpoint[(ServerRequest, String), TapirResponse, (String, CalibanPipe), ZioWebSockets] = {
85+
if (path.nonEmpty) {
86+
val p: List[EndpointInput[Unit]] = path.map(stringToPath)
87+
val fixedPath: EndpointInput[Unit] = p.tail.foldLeft(p.head)(_ / _)
88+
89+
interpreter.endpoint.prependIn(fixedPath)
90+
} else {
91+
interpreter.endpoint
92+
}
93+
}
94+
95+
def makeProtocol(
96+
serverRequest: ServerRequest,
97+
protocol: String
98+
): URIO[R, Either[TapirResponse, (String, CalibanPipe)]] =
99+
interpreter.makeProtocol(serverRequest, protocol)
100+
}
101+
77102
def apply[R, E](
78103
interpreter: GraphQLInterpreter[R, E],
79104
keepAliveTime: Option[Duration] = None,

0 commit comments

Comments
 (0)