Skip to content

OpenAPI example

examples/OpenApiExample shows the BaldrOpenApiExtension end-to-end: route metadata (WithSummary, WithOperationId, WithTag) feeds an auto-generated OpenAPI 3.0.3 document, and the Scalar UI is mounted alongside it.

Source

examples/OpenApiExample/src/main.cpp:

examples/OpenApiExample/src/main.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <Baldr/Baldr.hpp>

#include <optional>
#include <variant>

#include "Device.hpp"
#include "User.hpp"

namespace
{
    std::vector<User> makeUsers()
    {
        return std::vector<User> { User { .id = 1, .name = "First" },
                                   User { .id = 2, .name = "Second" } };
    }

    std::optional<User> findUser(int id)
    {
        for (const auto& u : makeUsers())
        {
            if (u.id == id)
                return u;
        }
        return std::nullopt;
    }
} // namespace

int main()
{
    auto builder =
        skr::ApplicationBuilder()
            .WithExtension<baldr::BaldrExtension>()
            .WithExtension<baldr::BaldrOpenApiExtension>(
                [](baldr::BaldrOpenApiExtension& openApi) {
                    baldr::OpenApiOptions opts;
                    opts.info.title       = "Devices API";
                    opts.info.version     = "1.0.0";
                    opts.info.description = "Reference example demonstrating "
                                            "RouteOptions + OpenAPI 3.0.3.";
                    openApi.WithOptions(opts);
                });

    auto app = builder.Build<baldr::WebApplication>();

    app->MapGroup("/api/v1", [](auto& group) {
        group.MapGet("/users")
            .WithSummary("Fetch users")
            .WithTag("users")
            .Handle([](baldr::HttpRequest&) { return makeUsers(); });

        group.MapGet("/users/:id")
            .WithSummary("Get a user by id")
            .WithTag("users")
            .Handle([](baldr::HttpRequest& request)
                        -> std::variant<
                            baldr::JsonResult<User, baldr::StatusCode::OK>,
                            baldr::BadRequestResult, baldr::NotFoundResult> {
                int id = 0;
                try
                {
                    id = std::stoi(request.params.at("id"));
                }
                catch (...)
                {
                    return baldr::Results::BadRequest();
                }

                auto found = findUser(id);
                if (!found)
                    return baldr::Results::NotFound();

                return baldr::Results::Json<User, baldr::StatusCode::OK>(
                    *found);
            });
    });

    baldr::MapScalarUi(*app);

    app->Run();

    return 0;
}

examples/OpenApiExample/src/Device.hpp:

Device.hpp
#pragma once

#include <string>

struct Device
{
    int         id;
    std::string uuid;
    std::string mac;
    std::string firmware;
    std::string created_at;
    std::string updated_at;
};

examples/OpenApiExample/src/User.hpp:

User.hpp
#pragma once

#include <string>

struct User
{
    int         id;
    std::string name;
};

What it shows

  • Wiring BaldrOpenApiExtension on the builder via .WithExtension<...>([](auto& ext){ ... }) and configuring OpenApiOptions (title / version / description).
  • Using the fluent RouteRegistration API: .WithSummary, .WithTag, .Handle(...).
  • Grouping routes under a common prefix with app->MapGroup("/api/v1", [](auto& group){ ... }).
  • Returning a std::variant of typed results from the users/:id handler (JsonResult / BadRequestResult / NotFoundResult) — the OpenAPI extension reflects on the success branch and emits the response schema.
  • Mounting baldr::MapScalarUi(*app) to expose the Scalar UI alongside the auto-generated spec.

Try it

cmake -S . -B build
cmake --build build
./build/OpenApiExample

In another terminal:

curl http://localhost:8080/openapi.json | jq '.paths, .components.schemas'
# Scalar UI is served at /scalar (open in a browser)

The document contains:

  • GET /api/v1/users — summary Fetch users, tagged users, response schema $ref to User.
  • GET /api/v1/users/:id — summary Get a user by id, tagged users, response schema $ref to User.
  • components.schemas.User — derived from the C++ struct.

Next steps