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