C++ RESTful web service with Swagger-UI and auto-documented endpoints
Tags: webdev, cpp, rest, swagger
Published: 2020-07-30 21:02:32

---
title: C++ RESTful web service with Swagger-UI and auto-documented endpoints
published: true
description: This is a 5 minutes tutorial how-to-use Oat++ C++ web framework to build your own C++ performant web-service and integrate it with Swagger-UI.
tags: webdev, cpp, REST, swagger
canonical_url: https://medium.com/oatpp/c-oatpp-web-service-with-swagger-ui-and-auto-documented-endpoints-1d4bb7b82c21
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/cw2z5pe8zoocgjz3ws4y.png
---

This is a 5 minutes tutorial how-to-use [Oat\+\+ web framework ](https://oatpp.io/)to build your own C\+\+ performant web-service and integrate it with Swagger-UI.

## Pre Requirements

* For **Mac/Linux**: Git, build-essentials, CMake.
* For **Windows**: Git, CMake, MSVC.

## Install Oat++

Clone oatpp repo:

```
$ git clone https://github.com/oatpp/oatpp
$ cd oatpp/
```

On Mac/Linux:

```shell
$ mkdir build && cd build/
$ cmake ..
$ make install
```

For more detailed instructions see - [installing Oat++ on Unix/Linux](https://oatpp.io/docs/installation/unix-linux/).

On Windows:

```shell
$ MD build
$ cd build/
$ cmake ..
$ cmake --build . --target INSTALL
```

For more detailed instructions see - [installing Oat++ on Windows](https://oatpp.io/docs/installation/windows/).

**Now we are able to build services using Oat++.** It is a zero-dependency framework, so NO additional installations are required.

---

## Build and Run Starter Project

Clone “oatpp-starter”

```
$ git clone --depth=1 https://github.com/oatpp/oatpp-starter my-service
$ cd my-service/
```

Build “oatpp-starter” on Mac/Linux

```shell
$ mkdir build && cd build/
$ cmake ..
$ make
```

Build “oatpp-starter” on Windows

```shell
$ MD build
$ cd build/
$ cmake ..
$ cmake --build .
```

Run compiled executable:

* Mac/Linux - `$ ./my-project-exe`
* Windows - `$ .\src\Debug\my-project-exe.exe`

Now go to [localhost:8000](http://localhost:8000/) and make sure that you can see the response from server

```json
{"statusCode": 200, "message": "Hello World!"}
```

---

## Project Structure

```
- src/
   |
   |- controller/              
   |   |
   |   |- MyController.hpp  // Endpoints are declared here
   |
   |- dto/
   |   |
   |   |- DTOs.hpp          // DTOs are here
   |
   |- App.cpp               // main is here
   |- AppComponent.hpp      // Application components configuration
```

**MyController class** - contains declared endpoints and their info together with additional Swagger annotations.

**MyDto class** - resides in DTOs.hpp. Describes the Data-Transfer-Object used in the "Hello World" response mentioned above. In oatpp DTOs are used in ObjectMapping and Serialization/Deserialization.

**App.cpp file** - this is an applications' entry point. Here Application Components are loaded, Controllers' endpoints are added to the Router, and the server starts.

**AppComponent class** - basically it is a collection of components that will be loaded on application start. Here we configure things like which ConnectionProvider to use, port to listen to, which ObjectMapper to use.

## Integrate Swagger-UI

To integrate Swagger-UI in the project we have to do the following:

* Clone and install [oatpp-swagger](https://github.com/oatpp/oatpp-swagger) module
* Add **oatpp-swagger** to **CMakeLists.txt**
* Add corresponding code to AppComponent.hpp and App.cpp

Install oatpp-swagger

```
$ git clone https://github.com/oatpp/oatpp-swagger
$ cd oatpp-swagger/
```

Linux/Mac:

```shell
$ mkdir build && cd build/
$ cmake ..
$ make install
```

Windows:

```shell
$ MD build
$ cd build/
$ cmake ..
$ cmake --build . --target INSTALL
```

Add **oatpp-swagger** to **CMakeLists.txt**

```
...

## add libs
find_package(oatpp          1.1.0 REQUIRED)
find_package(oatpp-swagger  1.1.0 REQUIRED) # <-- add this

target_link_libraries(${project_name}-lib
        PUBLIC oatpp::oatpp
        PUBLIC oatpp::oatpp-swagger         # <-- add this
)

## define path to swagger-ui res folder
add_definitions( 
  -DOATPP_SWAGGER_RES_PATH="${OATPP_BASE_DIR}/bin/oatpp-swagger/res"
) # <-- add this

...
```

## AppComponent.hpp

Here we add `oatpp::swagger::DocumentInfo` and `oatpp::swagger::Resources` components which give general information about our API document and specify a path to Swagger-UI resources:

```cpp
#include "oatpp-swagger/Model.hpp"
#include "oatpp-swagger/Resources.hpp"

...

class AppComponent {

...

  /**
   *  General API docs info
   */
  OATPP_CREATE_COMPONENT(
    std::shared_ptr<oatpp::swagger::DocumentInfo>, 
    swaggerDocumentInfo
  )([] {
    
    oatpp::swagger::DocumentInfo::Builder builder;
    builder
     .setTitle("My Demo Service with Swagger-UI")
     .setDescription("C++/oat++ Web Service with Swagger-UI")
     .setVersion("1.0")
     .setContactName("Mr. Developer")
     .setContactUrl("https://oatpp.io/")
     .setLicenseName("Apache License, Version 2.0")
     .setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
     .addServer("http://localhost:8000", "server on localhost");
     return builder.build();
  }());

  /**
   *  Swagger-Ui Resources
   */
  OATPP_CREATE_COMPONENT(
    std::shared_ptr<oatpp::swagger::Resources>, 
    swaggerResources
  )([] {
    return oatpp::swagger::Resources::loadResources(
      OATPP_SWAGGER_RES_PATH
    );
  }());

};
```

## App.cpp

Here we add `oatpp::swagger::Controller` to Router with the list of endpoints we want to document

```cpp
#include "oatpp-swagger/Controller.hpp"

...

void run() {
  
  ...

  auto docEndpoints =
    oatpp::swagger::Controller::Endpoints::createShared();

  docEndpoints->pushBackAll(myController->getEndpoints());

  auto swaggerController =
    oatpp::swagger::Controller::createShared(docEndpoints);
    
  swaggerController->addEndpointsToRouter(router);

  ...

}
```

---

Now if everything is ok, and `OATPP_SWAGGER_RES_PATH` path is set correctly in the **AppComponent.hpp**, we should be able to build and run our project and see Swagger-UI at [http://localhost:8000/swagger/ui](http://localhost:8000/swagger/ui) in the browser

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-wl963uah.png?alt=media&token=10cedd5d-11a3-4a31-a230-1f18817259bc)

## Additional Info for Endpoint

Our endpoint is already present in the document with the proper method and path. Oat\+\+ automatically documents most of the endpoints’ info, such as endpoint name, method, path, parameter names, and parameter types. However, there are things that should be specified explicitly.

## Annotate endpoint with additional information

In the file **MyController.hpp **we add `ENDPOINT_INFO` above the root `ENDPOINT` with summary and response information:

```cpp
ENDPOINT_INFO(root) {
  info->summary = "Root endpoint with 'Hello World!!!' message";
  info->addResponse<Object<MyDto>>(
    Status::CODE_200, 
    "application/json"
  );
}
ENDPOINT("GET", "/", root) {
  auto dto = MyDto::createShared();
  dto->statusCode = 200;
  dto->message = "Hello World!";
  return createDtoResponse(Status::CODE_200, dto);
}
```

Build, Run, and go to [http://localhost:8000/swagger/ui](http://localhost:8000/swagger/ui) in the browser. Refresh

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-ila03ucw.png?alt=media&token=fd91670e-5a4d-4aa9-833c-527bdcb1b1ef)

Notice, that summary is added to the endpoint and **MyDto schema automatically documented in the Models.**

Expand endpoint info and check that response is documented correctly

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-4sab3u0x.jpeg?alt=media&token=e01dcab5-0c88-4a9c-b274-25e530f7de52)

---

**Basically that’s it 🎉**

**Now we have Swagger-UI integrated into our project and we can easily add and document endpoints!**

---

## Add endpoint

Let’s add one more "echo" endpoint and see how it is documented in the swagger.

In the file **MyController.hpp:**

```cpp
ENDPOINT_INFO(echo) {
  info->summary = "Echo endpoint with custom message";
  info->addResponse<Object<MyDto>>(
    Status::CODE_200,
    "application/json"
  );
}
ENDPOINT("POST", "/echo/status/{status}", echo,
         PATH(Int32, status), BODY_STRING(String, message)) {
  auto dto = MyDto::createShared();
  dto->statusCode = status;
  dto->message = message;
  return createDtoResponse(Status::CODE_200, dto);
}
```

Build and run… Refresh…

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-qcbn3u41.png?alt=media&token=0b6e3dcd-3805-4a13-8611-b55b5062fa6a)

Expand echo endpoint info - you can see the "status" and "Request Body" parameters:

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-qzc83ut7.jpeg?alt=media&token=d577c399-bc6c-42d7-ba6d-f50720aa0a2d)

Put in some values:

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-31cj3u0y.jpeg?alt=media&token=14c43c69-7b27-4c20-8e02-3bcbd80ca62f)

Execute the request and verify that you have a correct response from the server:

![](https://firebasestorage.googleapis.com/v0/b/hackernoon-app.appspot.com/o/images%2F9zNYb5eBqhYDKibDyR5k0Kisqfm2-dscz3uz5.jpeg?alt=media&token=36a4d758-5f5a-4f86-bfc3-eaf1439ee3bd)

---

That’s it. You may experiment by adding more endpoints, playing with parameters, and DTO-fields to see how it is being documented in Swagger-UI.

---

## Useful Links

* **oatpp** repository - [https://github.com/oatpp/oatpp](https://github.com/oatpp/oatpp)
* **oatpp-swagger** repository - [https://github.com/oatpp/oatpp-swagger](https://github.com/oatpp/oatpp-swagger)
* Complete example project with basic CRUD implementation - [https://github.com/oatpp/example-crud](https://github.com/oatpp/example-crud)

‌