RESTful server Address Book Example | Qt HTTP Server 6.4.1

- Qt 6.4
- Qt HTTP Server
- Qt HTTP Server Examples
- RESTful server Address Book Example
- Qt 6.4.1 Reference Documentation

# 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();
     }