RESTful server Address Book Example

 // Copyright (C) 2022 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

 #include <QtCore>
 #include <QtHttpServer>

 #define API_KEY "SecretKey"

 struct ContactEntry
 {
     qint64 id;
     QString name;
     QString address;

     ContactEntry(const QString &name, const QString &address)
         : id(ContactEntry::nextId()), name(name), address(address)
     {
     }

     QJsonObject toJson() const
     {
         return QJsonObject{ { "id", id }, { "name", name }, { "address", address } };
     }

 private:
     static qint64 nextId();
 };

 qint64 ContactEntry::nextId()
 {
     static qint64 lastId = 0;
     return lastId++;
 }

 static bool checkApiKeyHeader(const QList<QPair<QByteArray, QByteArray>> &headers)
 {
     for (const auto &[key, value] : headers) {
         if (key == "api_key" && value == API_KEY) {
             return true;
         }
     }
     return false;
 }

 static QJsonObject insertAddress(QMap<qint64, ContactEntry> &contacts, const QString &name,
                                  const QString &address)
 {
     ContactEntry entry(name, address);
     const auto it = contacts.insert(entry.id, std::move(entry));
     return it->toJson();
 }

 static std::optional<QJsonObject> byteArrayToJsonObject(const QByteArray &arr)
 {
     QJsonParseError err;
     const auto json = QJsonDocument::fromJson(arr, &err);
     if (err.error || !json.isObject())
         return std::nullopt;
     return json.object();
 }

 int main(int argc, char *argv[])
 {
     QCoreApplication app(argc, argv);

     QMap<qint64, ContactEntry> contacts;
     // Setup QHttpServer
     QHttpServer httpServer;
     httpServer.route("/v2/contact", QHttpServerRequest::Method::Get,
                      [&contacts](const QHttpServerRequest &) {
                          QJsonArray array;
                          std::transform(contacts.cbegin(), contacts.cend(),
                                         std::inserter(array, array.begin()),
                                         [](const auto &it) { return it.toJson(); });

                          return QHttpServerResponse(array);
                      });

     httpServer.route("/v2/contact/<arg>", QHttpServerRequest::Method::Get,
                      [&contacts](qint64 contactId, const QHttpServerRequest &) {
                          const auto address = contacts.find(contactId);
                          return address != contacts.end()
                                  ? QHttpServerResponse(address->toJson())
                                  : QHttpServerResponse(QHttpServerResponder::StatusCode::NotFound);
                      });

     httpServer.route(
             "/v2/contact", QHttpServerRequest::Method::Post,
             [&contacts](const QHttpServerRequest &request) {
                 if (!checkApiKeyHeader(request.headers())) {
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);
                 }
                 const auto json = byteArrayToJsonObject(request.body());
                 if (!json || !json->contains("address") || !json->contains("name"))
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::BadRequest);
                 const auto entry = insertAddress(contacts, json->value("name").toString(),
                                                  json->value("address").toString());
                 return QHttpServerResponse(entry, QHttpServerResponder::StatusCode::Created);
             });

     httpServer.route(
             "/v2/contact/<arg>", QHttpServerRequest::Method::Put,
             [&contacts](qint64 contactId, const QHttpServerRequest &request) {
                 if (!checkApiKeyHeader(request.headers())) {
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);
                 }
                 const auto json = byteArrayToJsonObject(request.body());
                 if (!json || !json->contains("address") || !json->contains("name")) {
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::BadRequest);
                 }
                 auto address = contacts.find(contactId);
                 if (address == contacts.end())
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::NoContent);
                 address->name = json->value("name").toString();
                 address->address = json->value("address").toString();
                 return QHttpServerResponse(address->toJson());
             });

     httpServer.route(
             "/v2/contact/<arg>", QHttpServerRequest::Method::Patch,
             [&contacts](qint64 contactId, const QHttpServerRequest &request) {
                 if (!checkApiKeyHeader(request.headers())) {
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);
                 }
                 const auto json = byteArrayToJsonObject(request.body());
                 if (!json) {
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::BadRequest);
                 }
                 auto address = contacts.find(contactId);
                 if (address == contacts.end())
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::NoContent);
                 if (json->contains("name"))
                     address->name = json->value("name").toString();
                 if (json->contains("address"))
                     address->address = json->value("address").toString();
                 return QHttpServerResponse(address->toJson());
             });

     httpServer.route(
             "/v2/contact/<arg>", QHttpServerRequest::Method::Delete,
             [&contacts](qint64 contactId, const QHttpServerRequest &request) {
                 if (!checkApiKeyHeader(request.headers())) {
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);
                 }
                 if (!contacts.remove(contactId))
                     return QHttpServerResponse(QHttpServerResponder::StatusCode::NoContent);
                 return QHttpServerResponse(QHttpServerResponder::StatusCode::Ok);
             });

     const auto port = httpServer.listen(QHostAddress::Any);
     if (!port) {
         qDebug() << QCoreApplication::translate("QHttpServerExample",
                                                 "Server failed to listen on a port.");
         return 0;
     }

     qDebug() << QCoreApplication::translate(
                         "QHttpServerExample",
                         "Running on http://127.0.0.1:%1/ (Press CTRL+C to quit)")
                         .arg(port);

     return app.exec();
 }