Apidog

All-in-one Collaborative API Development Platform

API Design

API Documentation

API Debugging

API Mock

API Automated Testing

Sign up for free

How to Build and Test HTTP API Using Tapir

Start for free
Contents
Home / Applied skills / How to Build and Test HTTP API Using Tapir

How to Build and Test HTTP API Using Tapir

Tapir, a powerful tool in the Scala programming ecosystem. In this blog post, we will explore how Tapir streamlines the development and testing of HTTP APIs, making the creation of robust and reliable interfaces more accessible than ever.

In today's digital landscape, constructing and testing HTTP APIs is a fundamental task for software developers. To simplify this process, we turn our attention to Tapir, a powerful tool in the Scala programming ecosystem. In this blog post, we will explore how Tapir streamlines the development and testing of HTTP APIs, making the creation of robust and reliable interfaces more accessible than ever.

What is Tapir?

Tapir is an open-source API design and documentation tool based on the OpenAPI (Swagger) specification, while Swagger is a specification used for describing and documenting APIs. It simplifies API design and documentation, offering visual representation, comprehensive editing, automated documentation generation, multiple export formats, testing support, and code generation.

The Benefits of Tapir

Tapir is a Scala library that simplifies the process of building and testing HTTP APIs. It provides a type-safe, functional approach to defining API endpoints, request and response models, and routes. By using Tapir, you can enjoy several benefits, including:

  1. Type Safety: With Tapir, you define your API endpoints using Scala data types, ensuring that your API remains type-safe. This means that the compiler can catch many errors at compile time, reducing the chances of runtime issues.
  2. Documentation: Tapir allows you to document your API automatically. It generates documentation in various formats, such as OpenAPI (formerly known as Swagger), making it easier for clients and developers to understand and use your API.
  3. Code Generation: Tapir can generate server and client code based on your API definition. This saves development time and ensures that the client and server communicate seamlessly.
  4. Testing Support: Tapir integrates well with popular testing libraries, making it easy to write tests for your API endpoints.

Now, let's dive into the steps to build and test an HTTP API using Tapir.

A Step-by-step Guide to Create and Test an HTTP API  With Tapir

Step 1: Define Your API Endpoints

The first step is to define your API endpoints. You do this by creating data structures that represent the requests and responses of your API. Let's create a simple example of an API for managing tasks.

import sttp.tapir._
import sttp.tapir.generic.auto._
import sttp.tapir.json.circe._

case class Task(id: Int, description: String)

val getTasksEndpoint: Endpoint[Unit, String, List[Task], Any] =
  endpoint.get.in("tasks").errorOut(stringBody).out(jsonBody[List[Task]])

In this example, we define an endpoint for retrieving a list of tasks. We specify the request as having no input (represented by Unit) and the response as a list of tasks. We also define the error output.

Step 2: Implement Your API Routes

Now that you've defined your endpoints, it's time to implement the API routes. You can use your favorite web framework for this, such as Akka HTTP or Play Framework. In this example, we'll use the sttp library with the tapir-sttp module to define our routes.

import sttp.tapir.server.akkahttp._
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives._

implicit val system: ActorSystem = ActorSystem("api-system")

val routes: Route = getTasksEndpoint.toRoute(_ => {
  val tasks = List(Task(1, "Buy groceries"), Task(2, "Write a blog"))
  Right(tasks)
})

Http().newServerAt("localhost", 8080).bind(routes)

In this code, we define the routes for our getTasksEndpoint. When a request is made to the /tasks endpoint, the route responds with a list of tasks.

Step 3: Generate Documentation

One of the advantages of using Tapir is its ability to generate documentation automatically. To create documentation for your API, you can use the tapir-openapi-docs module.

import sttp.tapir.docs.openapi.OpenAPIDocsInterpreter
import sttp.tapir.openapi.circe.yaml._

val openApiDocs = OpenAPIDocsInterpreter().toOpenAPI(getTasksEndpoint, "Task API", "1.0")
val openApiYaml = openApiDocs.toYaml

The openApiYaml now contains the API documentation in OpenAPI format. You can expose this documentation to your API users, making it easier for them to understand and interact with your API.

Step 4: Test Your API

Testing your API is crucial to ensure that it behaves as expected. Tapir integrates seamlessly with testing libraries like scalatest. You can write test cases to validate your API's behavior.

import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import sttp.model.StatusCode
import sttp.client._
import sttp.tapir.client.sttp._

class TaskApiSpec extends AnyWordSpec with Matchers {
  "Task API" should {
    "return a list of tasks" in {
      val backend = HttpURLConnectionBackend()
      val response = getTasksEndpoint.toSttpRequest("http://localhost:8080").apply(()).send(backend)
      response.code shouldBe StatusCode.Ok
      response.body shouldBe Right("""[{"id":1,"description":"Buy groceries"},{"id":2,"description":"Write a blog"}]""")
    }
  }
}

In this test, we make a request to the API and validate the response to ensure that it matches our expectations.

Step 5: Code Generation

As a bonus, Tapir can generate client and server code based on your API definition. This is especially useful when you want to ensure consistency between the client and server, as well as reduce the amount of manual coding.

To generate code, you can use the tapir-generator module. For example, to generate a server route, you can run:

sbt "tapir-generator generate-endpoint -i <your-endpoint-file>.scala -d <output-directory>"

For a client, you can run:

sbt "tapir-generator generate-client -i <your-endpoint-file>.scala -d <output-directory>"

Apidog: Your User-Friendly API Developer Tool

While Tapir offers valuable capabilities, it may pose some challenges for newcomers, requiring familiarity with the OpenAPI specification and integration with other tools. For those seeking a more user-friendly API development solution, we recommend Apidog.

button

Apidog is a comprehensive API management platform offering documentation, debugging, mocking, and automation testing. It simplifies API management, supporting use case management, data model definition, automatic data structure verification during debugging, and visual assertion settings.

Key Benefits of Apidog:

Online API Documentation: Apidog provides a platform for creating, testing, and managing APIs, offering clear and comprehensive documentation based on OpenAPI and JSON Schema standards. Customize and share this documentation with interactive features, such as trying out the server and viewing examples.

Code Generation: Apidog can automatically generate code snippets in over 130 programming languages and frameworks, saving time and effort for developers.

Code Generation

Import/Export Functionality: Seamlessly integrate Apidog with other tools by exporting data in various formats like OpenAPI, Markdown, and HTML. Import data from sources like OpenAPI, Postman, and YApi for easier project migration.

Import/Export
How to Import/Export Postman Collection Data
In this article, we will discuss how to import/export Postman collections and explore alternative method to fix it, which offer more flexibility without any restrictions on the number of runs.

Conclusion

In this blog post, we explored how to build and test an HTTP API using Tapir, a powerful library for Scala developers. Tapir's type-safe approach, automatic documentation generation, and integration with testing libraries make it a valuable tool for developing high-quality APIs.