- Qt 6.10
- Qt HTTP Server
- Qt HTTP Server Examples
- RESTful API Server
- Qt 6.10.2 Reference Documentation

# RESTful API Server

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

     #include "apibehavior.h"
     #include "types.h"
     #include "utils.h"
     #include <QtCore/QCoreApplication>
     #include <QtHttpServer/QHttpServer>

     #define SCHEME "http"
     #define HOST "127.0.0.1"
     #define PORT 49425

     template<typename T>
     void addCrudRoutes(QHttpServer &httpServer, const QString &apiPath, CrudApi<T> &api,
                        const SessionApi &sessionApi)
     {
         httpServer.route(
                 QString("%1").arg(apiPath), QHttpServerRequest::Method::Get,
                 [&api](const QHttpServerRequest &request) { return api.getPaginatedList(request); });

         httpServer.route(QString("%1/<arg>").arg(apiPath), QHttpServerRequest::Method::Get,
                          [&api](qint64 itemId) { return api.getItem(itemId); });

         httpServer.route(QString("%1").arg(apiPath), QHttpServerRequest::Method::Post,
                          [&api, &sessionApi](const QHttpServerRequest &request) {
                              if (!sessionApi.authorize(request)) {
                                  return QHttpServerResponse(
                                          QHttpServerResponder::StatusCode::Unauthorized);
                              }
                              return api.postItem(request);
                          });

         httpServer.route(QString("%1/<arg>").arg(apiPath), QHttpServerRequest::Method::Put,
                          [&api, &sessionApi](qint64 itemId, const QHttpServerRequest &request) {
                              if (!sessionApi.authorize(request)) {
                                  return QHttpServerResponse(
                                          QHttpServerResponder::StatusCode::Unauthorized);
                              }
                              return api.updateItem(itemId, request);
                          });

         httpServer.route(QString("%1/<arg>").arg(apiPath), QHttpServerRequest::Method::Patch,
                          [&api, &sessionApi](qint64 itemId, const QHttpServerRequest &request) {
                              if (!sessionApi.authorize(request)) {
                                  return QHttpServerResponse(
                                          QHttpServerResponder::StatusCode::Unauthorized);
                              }
                              return api.updateItemFields(itemId, request);
                          });

         httpServer.route(QString("%1/<arg>").arg(apiPath), QHttpServerRequest::Method::Delete,
                          [&api, &sessionApi](qint64 itemId, const QHttpServerRequest &request) {
                              if (!sessionApi.authorize(request)) {
                                  return QHttpServerResponse(
                                          QHttpServerResponder::StatusCode::Unauthorized);
                              }
                              return api.deleteItem(itemId);
                          });
     }

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

         QCommandLineParser parser;
         parser.addOptions({
                 { "port", QCoreApplication::translate("main", "The port the server listens on."),
                   "port" },
         });
         parser.addHelpOption();
         parser.process(app);

         quint16 portArg = PORT;
         if (!parser.value("port").isEmpty())
             portArg = parser.value("port").toUShort();

         auto colorFactory = std::make_unique<ColorFactory>();
         auto colors = tryLoadFromFile<Color>(*colorFactory, ":/assets/colors.json");
         CrudApi<Color> colorsApi(std::move(colors), std::move(colorFactory));

         auto userFactory = std::make_unique<UserFactory>(SCHEME, HOST, portArg);
         auto users = tryLoadFromFile<User>(*userFactory, ":/assets/users.json");
         CrudApi<User> usersApi(std::move(users), std::move(userFactory));

         auto sessionEntryFactory = std::make_unique<SessionEntryFactory>();
         auto sessions = tryLoadFromFile<SessionEntry>(*sessionEntryFactory, ":/assets/sessions.json");
         SessionApi sessionApi(std::move(sessions), std::move(sessionEntryFactory));

         // Setup QHttpServer
         QHttpServer httpServer;
         httpServer.route("/", []() {
             return "Qt Colorpalette example server. Please see documentation for API description";
         });

         addCrudRoutes(httpServer, "/api/unknown", colorsApi, sessionApi);
         addCrudRoutes(httpServer, "/api/users", usersApi, sessionApi);

         // Login resource
         httpServer.route(
                 "/api/login", QHttpServerRequest::Method::Post,
                 [&sessionApi](const QHttpServerRequest &request) { return sessionApi.login(request); });

         httpServer.route("/api/register", QHttpServerRequest::Method::Post,
                          [&sessionApi](const QHttpServerRequest &request) {
                              return sessionApi.registerSession(request);
                          });

         httpServer.route("/api/logout", QHttpServerRequest::Method::Post,
                          [&sessionApi](const QHttpServerRequest &request) {
                              return sessionApi.logout(request);
                          });

         // Images resource
         httpServer.route("/img/faces/<arg>-image.jpg", QHttpServerRequest::Method::Get,
                          [](qint64 imageId, const QHttpServerRequest &) {
                              return QHttpServerResponse::fromFile(
                                      QString(":/assets/img/%1-image.jpg").arg(imageId));
                          });

         auto tcpserver = std::make_unique<QTcpServer>();
         if (!tcpserver->listen(QHostAddress::Any, portArg) || !httpServer.bind(tcpserver.get())) {
             qDebug() << QCoreApplication::translate("QHttpServerExample",
                                                     "Server failed to listen on a port.");
             return 0;
         }
         quint16 port = tcpserver->serverPort();
         tcpserver.release();

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

         return app.exec();
     }