# Http Adapters

Once you have an interpreter able to execute GraphQL queries, you usually want to expose it using an HTTP API. Caliban comes with a few "ready-to-use" components (called "adapters") to expose your API with the most popular HTTP libraries.

Under the hood, adapters use the tapir (opens new window) library, so you can easily create a custom adapter with anything that tapir supports.

# Built-in adapters

Each built-in adapter comes with 3 main functions:

Each of these functions also support a few parameters:

  • skipValidation (default: false) allows skipping validation when executing requests
  • enableIntrospection (default: true) allows disabling introspection
  • queryExecution (default: Parallel) defines how query optimization should work
  • requestInterceptor (default: empty) allows intercepting data from the request (e.g. headers) and do something with it (e.g. save it inside ZIO env)
  • webSocketHooks (default: empty) gives you some hooks around the WebSocket lifecycle (useful for authentication)

The following adapters are provided:

  • Http4sAdapter exposes a route for http4s, using circe for the Json handling.
  • ZHttpAdapter exposes a route for zio-http, using circe for the Json handling. This one doesn't support upload yet.
  • PlayHttpAdapter exposes a route for play, using play-json for the Json handling.
  • AkkaHttpAdapter exposes a route for akka. For historical reasons, this adapter is not fixed to any Json library, which means that you need depend on one of the tapir Json libraries and import it.

Want to use something else? Want to use one of them with a different Json library? Check the next section!

Make sure to check the examples to see the adapters in action.

# Make your own adapter

All existing adapters are actually using a common adapter under the hood, called TapirAdapter.

This adapter, available in the caliban-tapir dependency, also have the same 3 methods makeHttpService, makeHttpUploadService and makeWebSocketService. There are 2 main differences between these and the methods from the built-in adapters:

  • they return one or several tapir ServerEndpoint, which you can then pass to a tapir interpreter. The returned ServerEndpoint use RIO[R, *] as an effect type, but you can easily transform it to another effect type. A helper convertHttpEndpointToFuture allows converting the effect type to a scala Future (this is used in the Akka and Play interpreters).
  • they require some implicit JsonCodec, which you can get by importing the proper tapir json object

Let's say we want to use http4s but with play-json instead of circe. The built-in Http4sAdapter uses circe so instead, we will directly use TapirAdapter. First, we need to import 2 tapir dependencies in our project (in addition to caliban-tapir):

  • a tapir interpreter for http4s: tapir-zio-http4s-server
  • a tapir json codec for play-json: tapir-json-play
import sttp.tapir.json.play._
import sttp.tapir.server.http4s.ztapir.ZHttp4sServerInterpreter

val endpoints   = TapirAdapter.makeHttpService(interpreter)
val http4sRoute = ZHttp4sServerInterpreter().from(endpoints).toRoutes

That's it! http4sRoute is a valid http4s route ready to serve our API.

Limitations

The zio-http interpreter in tapir does not include multipart and websocket support.

Caliban comes with json encoders and decoders for circe, zio-json and play-json. If you use another json library, you will need to create encoders and decoders for it (which is very simple, you can simply look at the existing ones).