Skip to content

Commit

Permalink
Allow prepending input path to HttpInterpreter generated Tapir endpoi…
Browse files Browse the repository at this point in the history
…nts (#2188)
  • Loading branch information
olisikh authored Apr 14, 2024
1 parent 8e6950b commit 3ddc3e0
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,24 @@ sealed trait HttpInterpreter[-R, E] { self =>
serverRequest: ServerRequest
)(implicit streamConstructor: StreamConstructor[BS]): ZIO[R, TapirResponse, CalibanResponse[BS]]

def serverEndpoints[R1 <: R, S](stream: Streams[S])(implicit
streamConstructor: StreamConstructor[stream.BinaryStream]
): List[CalibanEndpoint[R1, stream.BinaryStream, S]] = {
def serverEndpoints[R1 <: R, S](streams: Streams[S])(implicit
streamConstructor: StreamConstructor[streams.BinaryStream]
): List[CalibanEndpoint[R1, streams.BinaryStream, S]] = {
def logic(
request: (GraphQLRequest, ServerRequest)
): RIO[R1, Either[TapirResponse, CalibanResponse[stream.BinaryStream]]] = {
): RIO[R1, Either[TapirResponse, CalibanResponse[streams.BinaryStream]]] = {
val (graphQLRequest, serverRequest) = request
executeRequest(graphQLRequest, serverRequest).either
}
endpoints[S](stream).map(_.serverLogic(logic(_)))
endpoints[S](streams).map(_.serverLogic(logic(_)))
}

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

def prependPath(path: List[String]): HttpInterpreter[R, E] =
HttpInterpreter.Prepended(self, path)

def configure[R1](configurator: Configurator[R1]): HttpInterpreter[R & R1, E] =
intercept[R & R1](ZLayer.scopedEnvironment[R & R1 & ServerRequest](configurator *> ZIO.environment[R]))
}
Expand Down Expand Up @@ -63,6 +66,33 @@ object HttpInterpreter {
}
}

private case class Prepended[R, E](
interpreter: HttpInterpreter[R, E],
path: List[String]
) extends HttpInterpreter[R, E] {
override def endpoints[S](
streams: Streams[S]
): List[
PublicEndpoint[(GraphQLRequest, ServerRequest), TapirResponse, CalibanResponse[streams.BinaryStream], S]
] = {
val endpoints = interpreter.endpoints(streams)
if (path.nonEmpty) {
val p: List[EndpointInput[Unit]] = path.map(stringToPath)
val fixedPath: EndpointInput[Unit] = p.tail.foldLeft(p.head)(_ / _)

endpoints.map(_.prependIn(fixedPath))
} else {
endpoints
}
}

def executeRequest[BS](
graphQLRequest: GraphQLRequest,
serverRequest: ServerRequest
)(implicit streamConstructor: StreamConstructor[BS]): ZIO[R, TapirResponse, CalibanResponse[BS]] =
interpreter.executeRequest(graphQLRequest, serverRequest)
}

private case class Intercepted[R1, R, E](
interpreter: HttpInterpreter[R, E],
layer: ZLayer[R1 & ServerRequest, TapirResponse, R]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ sealed trait HttpUploadInterpreter[-R, E] { self =>
def intercept[R1](interceptor: Interceptor[R1, R]): HttpUploadInterpreter[R1, E] =
HttpUploadInterpreter.Intercepted(self, interceptor)

def prependPath(path: List[String]): HttpUploadInterpreter[R, E] =
HttpUploadInterpreter.Prepended(self, path)

def configure[R1](configurator: Configurator[R1]): HttpUploadInterpreter[R & R1, E] =
intercept[R & R1](ZLayer.scopedEnvironment[R & R1 & ServerRequest](configurator *> ZIO.environment[R]))
}
Expand Down Expand Up @@ -123,6 +126,31 @@ object HttpUploadInterpreter {
interpreter.executeRequest(graphQLRequest, serverRequest).provideSome[R1](ZLayer.succeed(serverRequest), layer)
}

private case class Prepended[R, E](
interpreter: HttpUploadInterpreter[R, E],
path: List[String]
) extends HttpUploadInterpreter[R, E] {
override def endpoint[S](
streams: Streams[S]
): PublicEndpoint[UploadRequest, TapirResponse, CalibanResponse[streams.BinaryStream], S] = {
val endpoints = interpreter.endpoint(streams)
if (path.nonEmpty) {
val p: List[EndpointInput[Unit]] = path.map(stringToPath)
val fixedPath: EndpointInput[Unit] = p.tail.foldLeft(p.head)(_ / _)

endpoints.prependIn(fixedPath)
} else {
endpoints
}
}

def executeRequest[BS](
graphQLRequest: GraphQLRequest,
serverRequest: ServerRequest
)(implicit streamConstructor: StreamConstructor[BS]): ZIO[R, TapirResponse, CalibanResponse[BS]] =
interpreter.executeRequest(graphQLRequest, serverRequest)
}

def apply[R, E](
interpreter: GraphQLInterpreter[R, E]
)(implicit responseValueCodec: JsonCodec[ResponseValue]): HttpUploadInterpreter[R, E] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ sealed trait WebSocketInterpreter[-R, E] { self =>
def intercept[R1](interceptor: Interceptor[R1, R]): WebSocketInterpreter[R1, E] =
WebSocketInterpreter.Intercepted(self, interceptor)

def prependPath(path: List[String]): WebSocketInterpreter[R, E] =
WebSocketInterpreter.Prepended(self, path)

def configure[R1](configurator: Configurator[R1]): WebSocketInterpreter[R & R1, E] =
intercept[R & R1](ZLayer.scopedEnvironment[R & R1 & ServerRequest](configurator *> ZIO.environment[R]))
}
Expand Down Expand Up @@ -74,6 +77,28 @@ object WebSocketInterpreter {
.catchAll(ZIO.left(_))
}

private case class Prepended[R, E](
interpreter: WebSocketInterpreter[R, E],
path: List[String]
) extends WebSocketInterpreter[R, E] {
val endpoint: PublicEndpoint[(ServerRequest, String), TapirResponse, (String, CalibanPipe), ZioWebSockets] = {
if (path.nonEmpty) {
val p: List[EndpointInput[Unit]] = path.map(stringToPath)
val fixedPath: EndpointInput[Unit] = p.tail.foldLeft(p.head)(_ / _)

interpreter.endpoint.prependIn(fixedPath)
} else {
interpreter.endpoint
}
}

def makeProtocol(
serverRequest: ServerRequest,
protocol: String
): URIO[R, Either[TapirResponse, (String, CalibanPipe)]] =
interpreter.makeProtocol(serverRequest, protocol)
}

def apply[R, E](
interpreter: GraphQLInterpreter[R, E],
keepAliveTime: Option[Duration] = None,
Expand Down

0 comments on commit 3ddc3e0

Please sign in to comment.