This is a 5 minutes tutorial how-to-use Oat++ (AKA oatpp) web framework to build your own C++ performant web-service and integrate it with Swagger-UI.
Clone oatpp repo:
$ git clone https://github.com/oatpp/oatpp
$ cd oatpp/
On Mac/Linux:
$ mkdir build && cd build/
$ cmake ..
$ make install
For more detailed instructions see - installing Oat++ on Unix/Linux.
On Windows:
$ MD build
$ cd build/
$ cmake ..
$ 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.
Clone “oatpp-starter”
$ git clone --depth=1 https://github.com/oatpp/oatpp-starter my-service
$ cd my-service/
Build “oatpp-starter” on Mac/Linux
$ mkdir build && cd build/
$ cmake ..
$ make
Build “oatpp-starter” on Windows
$ MD build
$ cd build/
$ cmake ..
$ cmake --build .
Run compiled executable:
$ ./my-project-exe
$ .\src\Debug\my-project-exe.exe
Now go to localhost:8000 and make sure that you can see the response from server
{"statusCode": 200, "message": "Hello World!"}
- src/
|
|- controller/
| |
| |- MyController.hpp // Endpoints are declared here
|
|- dto/
| |
| |- DTOs.hpp // DTOs are here
|
|- App.cpp // main is here
|- AppComponent.hpp // Application components configuration
To integrate Swagger-UI in the project we have to do the following:
Install oatpp-swagger
$ git clone https://github.com/oatpp/oatpp-swagger
$ cd oatpp-swagger/
Linux/Mac:
$ mkdir build && cd build/
$ cmake ..
$ make install
Windows:
$ 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
...
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:#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
);
}());
};
Here we add
oatpp::swagger::Controller
to Router with the list of endpoints we want to document#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 in the browserOur 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.
In the file MyController.hpp we add
ENDPOINT_INFO
above the root ENDPOINT
with summary and response information: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 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!
Let’s add one more "echo" endpoint and see how it is documented in the swagger.
In the file MyController.hpp:
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…
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.
Previously published at https://medium.com/oatpp/c-oatpp-web-service-with-swagger-ui-and-auto-documented-endpoints-1d4bb7b82c21