{{announcement.body}}
{{announcement.title}}

C++ RESTful Web Service With Swagger-UI and Auto-Documented Endpoints

DZone 's Guide to

C++ RESTful Web Service With Swagger-UI and Auto-Documented Endpoints

This is a 5 minutes tutorial how-to-use Oat++ web framework to build your own C++ performant web-service and integrate it with Swagger-UI.

· IoT Zone ·
Free Resource

This is a 5 minutes tutorial how-to-use Oat++ web framework 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:

Shell
 




x


 
1
$ git clone https://github.com/oatpp/oatpp
2
$ cd oatpp/



On Mac/Linux:

Shell
 




xxxxxxxxxx
1


 
1
$ mkdir build && cd build/
2
$ cmake ..
3
$ make install



For more detailed instructions see - installing Oat++ on Unix/Linux.

On Windows:

PowerShell
 




xxxxxxxxxx
1


 
1
$ MD build
2
$ cd build/
3
$ cmake ..
4
$ cmake --build . --target INSTALL



For more detailed instructions see - installing Oat++ on 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”

Shell
 




xxxxxxxxxx
1


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



Build “oatpp-starter” on Mac/Linux

Shell
 




xxxxxxxxxx
1


 
1
$ mkdir build && cd build/
2
$ cmake ..
3
$ make



Build “oatpp-starter” on Windows

PowerShell
 




xxxxxxxxxx
1


 
1
$ MD build
2
$ cd build/
3
$ cmake ..
4
$ cmake --build .



Run compiled executable:

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

Now go to localhost:8000 and make sure that you can see the response from server

JSON
 




xxxxxxxxxx
1


 
1
{"statusCode": 200, "message": "Hello World!"}



Project Structure

Shell
 




xxxxxxxxxx
1
12


 
1
- src/
2
   |
3
   |- controller/              
4
   |   |
5
   |   |- MyController.hpp  // Endpoints are declared here
6
   |
7
   |- dto/
8
   |   |
9
   |   |- DTOs.hpp          // DTOs are here
10
   |
11
   |- App.cpp               // main is here
12
   |- 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 module
  • Add oatpp-swagger to CMakeLists.txt
  • Add corresponding code to AppComponent.hpp and App.cpp

Install oatpp-swagger

Shell
 




xxxxxxxxxx
1


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



Linux/Mac:

Shell
 




xxxxxxxxxx
1


 
1
$ mkdir build && cd build/
2
$ cmake ..
3
$ make install



Windows:

PowerShell
 




xxxxxxxxxx
1


 
1
$ MD build
2
$ cd build/
3
$ cmake ..
4
$ cmake --build . --target INSTALL



Add oatpp-swagger to CMakeLists.txt

CMake
 




xxxxxxxxxx
1
17


 
1
...
2
 
          
3
## add libs
4
find_package(oatpp          1.1.0 REQUIRED)
5
find_package(oatpp-swagger  1.1.0 REQUIRED) # <-- add this
6
 
          
7
target_link_libraries(${project_name}-lib
8
        PUBLIC oatpp::oatpp
9
        PUBLIC oatpp::oatpp-swagger         # <-- add this
10
)
11
 
          
12
## define path to swagger-ui res folder
13
add_definitions( 
14
  -DOATPP_SWAGGER_RES_PATH="${OATPP_BASE_DIR}/bin/oatpp-swagger/res"
15
) # <-- add this
16
 
          
17
...



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:

C++
 




xxxxxxxxxx
1
43


 
1
#include "oatpp-swagger/Model.hpp"
2
#include "oatpp-swagger/Resources.hpp"
3
 
          
4
...
5
 
          
6
class AppComponent {
7
 
          
8
...
9
 
          
10
  /**
11
   *  General API docs info
12
   */
13
  OATPP_CREATE_COMPONENT(
14
    std::shared_ptr<oatpp::swagger::DocumentInfo>, 
15
    swaggerDocumentInfo
16
  )([] {
17
 
          
18
    oatpp::swagger::DocumentInfo::Builder builder;
19
    builder
20
     .setTitle("My Demo Service with Swagger-UI")
21
     .setDescription("C++/oat++ Web Service with Swagger-UI")
22
     .setVersion("1.0")
23
     .setContactName("Mr. Developer")
24
     .setContactUrl("https://oatpp.io/")
25
     .setLicenseName("Apache License, Version 2.0")
26
     .setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
27
     .addServer("http://localhost:8000", "server on localhost");
28
     return builder.build();
29
  }());
30
 
          
31
  /**
32
   *  Swagger-Ui Resources
33
   */
34
  OATPP_CREATE_COMPONENT(
35
    std::shared_ptr<oatpp::swagger::Resources>, 
36
    swaggerResources
37
  )([] {
38
    return oatpp::swagger::Resources::loadResources(
39
      OATPP_SWAGGER_RES_PATH
40
    );
41
  }());
42
 
          
43
};


App.cpp

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

C++
 




xxxxxxxxxx
1
21


 
1
#include "oatpp-swagger/Controller.hpp"
2
 
          
3
...
4
 
          
5
void run() {
6
 
          
7
  ...
8
 
          
9
  auto docEndpoints =
10
    oatpp::swagger::Controller::Endpoints::createShared();
11
 
          
12
  docEndpoints->pushBackAll(myController->getEndpoints());
13
 
          
14
  auto swaggerController =
15
    oatpp::swagger::Controller::createShared(docEndpoints);
16
 
          
17
  swaggerController->addEndpointsToRouter(router);
18
 
          
19
  ...
20
 
          
21
}



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 in the browser.

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:

C++
 




xxxxxxxxxx
1
13


 
1
ENDPOINT_INFO(root) {
2
  info->summary = "Root endpoint with 'Hello World!!!' message";
3
  info->addResponse<Object<MyDto>>(
4
    Status::CODE_200, 
5
    "application/json"
6
  );
7
}
8
ENDPOINT("GET", "/", root) {
9
  auto dto = MyDto::createShared();
10
  dto->statusCode = 200;
11
  dto->message = "Hello World!";
12
  return createDtoResponse(Status::CODE_200, dto);
13
}



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

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


Basically that’s it!!!

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


Add Andpoint

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

In the file MyController.hpp:

C++
 




xxxxxxxxxx
1
14


 
1
ENDPOINT_INFO(echo) {
2
  info->summary = "Echo endpoint with custom message";
3
  info->addResponse<Object<MyDto>>(
4
    Status::CODE_200,
5
    "application/json"
6
  );
7
}
8
ENDPOINT("POST", "/echo/status/{status}", echo,
9
         PATH(Int32, status), BODY_STRING(String, message)) {
10
  auto dto = MyDto::createShared();
11
  dto->statusCode = status;
12
  dto->message = message;
13
  return createDtoResponse(Status::CODE_200, dto);
14
}



Build and run… Refresh…

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

Put in some values:

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


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

Topics:
c++, cpp, open api, rest api, swagger, swagger 2, swagger ui, tutorial, web developement, web framework

Published at DZone with permission of Leonid St . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}