<@comment>// Copyright (C) 2022 The Qt Company Ltd.</@comment>
<@comment>// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause</@comment>
<@preprocessor>#include "apibehavior.h"</@preprocessor>
<@preprocessor>#include "types.h"</@preprocessor>
<@preprocessor>#include "utils.h"</@preprocessor>
<@preprocessor>#include <QtCore/QCoreApplication></@preprocessor>
<@preprocessor>#include <QtHttpServer/QHttpServer></@preprocessor>
<@preprocessor>#define SCHEME "http"</@preprocessor>
<@preprocessor>#define HOST "127.0.0.1"</@preprocessor>
<@preprocessor>#define PORT 49425</@preprocessor>
<@keyword>template</@keyword><@op><</@op><@keyword>typename</@keyword> T<@op>></@op>
<@type>void</@type> addCrudRoutes(<@type>QHttpServer</@type> <@op>&</@op>httpServer<@op>,</@op> <@keyword>const</@keyword> <@type>QString</@type> <@op>&</@op>apiPath<@op>,</@op> CrudApi<@op><</@op>T<@op>></@op> <@op>&</@op>api<@op>,</@op>
<@keyword>const</@keyword> SessionApi <@op>&</@op>sessionApi)
{
httpServer<@op>.</@op>route(
<@type>QString</@type>(<@string>"%1"</@string>)<@op>.</@op>arg(apiPath)<@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Get<@op>,</@op>
<@op>[</@op><@op>&</@op>api<@op>]</@op>(<@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) { <@keyword>return</@keyword> api<@op>.</@op>getPaginatedList(request); });
httpServer<@op>.</@op>route(<@type>QString</@type>(<@string>"%1/<arg>"</@string>)<@op>.</@op>arg(apiPath)<@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Get<@op>,</@op>
<@op>[</@op><@op>&</@op>api<@op>]</@op>(<@type>qint64</@type> itemId) { <@keyword>return</@keyword> api<@op>.</@op>getItem(itemId); });
httpServer<@op>.</@op>route(<@type>QString</@type>(<@string>"%1"</@string>)<@op>.</@op>arg(apiPath)<@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Post<@op>,</@op>
<@op>[</@op><@op>&</@op>api<@op>,</@op> <@op>&</@op>sessionApi<@op>]</@op>(<@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) {
<@keyword>if</@keyword> (<@op>!</@op>sessionApi<@op>.</@op>authorize(request)) {
<@keyword>return</@keyword> <@type>QHttpServerResponse</@type>(
<@type>QHttpServerResponder</@type><@op>::</@op>StatusCode<@op>::</@op>Unauthorized);
}
<@keyword>return</@keyword> api<@op>.</@op>postItem(request);
});
httpServer<@op>.</@op>route(<@type>QString</@type>(<@string>"%1/<arg>"</@string>)<@op>.</@op>arg(apiPath)<@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Put<@op>,</@op>
<@op>[</@op><@op>&</@op>api<@op>,</@op> <@op>&</@op>sessionApi<@op>]</@op>(<@type>qint64</@type> itemId<@op>,</@op> <@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) {
<@keyword>if</@keyword> (<@op>!</@op>sessionApi<@op>.</@op>authorize(request)) {
<@keyword>return</@keyword> <@type>QHttpServerResponse</@type>(
<@type>QHttpServerResponder</@type><@op>::</@op>StatusCode<@op>::</@op>Unauthorized);
}
<@keyword>return</@keyword> api<@op>.</@op>updateItem(itemId<@op>,</@op> request);
});
httpServer<@op>.</@op>route(<@type>QString</@type>(<@string>"%1/<arg>"</@string>)<@op>.</@op>arg(apiPath)<@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Patch<@op>,</@op>
<@op>[</@op><@op>&</@op>api<@op>,</@op> <@op>&</@op>sessionApi<@op>]</@op>(<@type>qint64</@type> itemId<@op>,</@op> <@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) {
<@keyword>if</@keyword> (<@op>!</@op>sessionApi<@op>.</@op>authorize(request)) {
<@keyword>return</@keyword> <@type>QHttpServerResponse</@type>(
<@type>QHttpServerResponder</@type><@op>::</@op>StatusCode<@op>::</@op>Unauthorized);
}
<@keyword>return</@keyword> api<@op>.</@op>updateItemFields(itemId<@op>,</@op> request);
});
httpServer<@op>.</@op>route(<@type>QString</@type>(<@string>"%1/<arg>"</@string>)<@op>.</@op>arg(apiPath)<@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Delete<@op>,</@op>
<@op>[</@op><@op>&</@op>api<@op>,</@op> <@op>&</@op>sessionApi<@op>]</@op>(<@type>qint64</@type> itemId<@op>,</@op> <@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) {
<@keyword>if</@keyword> (<@op>!</@op>sessionApi<@op>.</@op>authorize(request)) {
<@keyword>return</@keyword> <@type>QHttpServerResponse</@type>(
<@type>QHttpServerResponder</@type><@op>::</@op>StatusCode<@op>::</@op>Unauthorized);
}
<@keyword>return</@keyword> api<@op>.</@op>deleteItem(itemId);
});
}
<@type>int</@type> main(<@type>int</@type> argc<@op>,</@op> <@type>char</@type> <@op>*</@op>argv<@op>[</@op><@op>]</@op>)
{
<@type>QCoreApplication</@type> app(argc<@op>,</@op> argv);
<@type>QCommandLineParser</@type> parser;
parser<@op>.</@op>addOptions({
{ <@string>"port"</@string><@op>,</@op> <@type>QCoreApplication</@type><@op>::</@op>translate(<@string>"main"</@string><@op>,</@op> <@string>"The port the server listens on."</@string>)<@op>,</@op>
<@string>"port"</@string> }<@op>,</@op>
});
parser<@op>.</@op>addHelpOption();
parser<@op>.</@op>process(app);
<@type>quint16</@type> portArg <@op>=</@op> PORT;
<@keyword>if</@keyword> (<@op>!</@op>parser<@op>.</@op>value(<@string>"port"</@string>)<@op>.</@op>isEmpty())
portArg <@op>=</@op> parser<@op>.</@op>value(<@string>"port"</@string>)<@op>.</@op>toUShort();
<@keyword>auto</@keyword> colorFactory <@op>=</@op> std<@op>::</@op>make_unique<@op><</@op>ColorFactory<@op>></@op>();
<@keyword>auto</@keyword> colors <@op>=</@op> tryLoadFromFile<@op><</@op>Color<@op>></@op>(<@op>*</@op>colorFactory<@op>,</@op> <@string>":/assets/colors.json"</@string>);
CrudApi<@op><</@op>Color<@op>></@op> colorsApi(std<@op>::</@op>move(colors)<@op>,</@op> std<@op>::</@op>move(colorFactory));
<@keyword>auto</@keyword> userFactory <@op>=</@op> std<@op>::</@op>make_unique<@op><</@op>UserFactory<@op>></@op>(SCHEME<@op>,</@op> HOST<@op>,</@op> portArg);
<@keyword>auto</@keyword> users <@op>=</@op> tryLoadFromFile<@op><</@op>User<@op>></@op>(<@op>*</@op>userFactory<@op>,</@op> <@string>":/assets/users.json"</@string>);
CrudApi<@op><</@op>User<@op>></@op> usersApi(std<@op>::</@op>move(users)<@op>,</@op> std<@op>::</@op>move(userFactory));
<@keyword>auto</@keyword> sessionEntryFactory <@op>=</@op> std<@op>::</@op>make_unique<@op><</@op>SessionEntryFactory<@op>></@op>();
<@keyword>auto</@keyword> sessions <@op>=</@op> tryLoadFromFile<@op><</@op>SessionEntry<@op>></@op>(<@op>*</@op>sessionEntryFactory<@op>,</@op> <@string>":/assets/sessions.json"</@string>);
SessionApi sessionApi(std<@op>::</@op>move(sessions)<@op>,</@op> std<@op>::</@op>move(sessionEntryFactory));
<@comment>// Setup QHttpServer</@comment>
<@type>QHttpServer</@type> httpServer;
httpServer<@op>.</@op>route(<@string>"/"</@string><@op>,</@op> <@op>[</@op><@op>]</@op>() {
<@keyword>return</@keyword> <@string>"Qt Colorpalette example server. Please see documentation for API description"</@string>;
});
addCrudRoutes(httpServer<@op>,</@op> <@string>"/api/unknown"</@string><@op>,</@op> colorsApi<@op>,</@op> sessionApi);
addCrudRoutes(httpServer<@op>,</@op> <@string>"/api/users"</@string><@op>,</@op> usersApi<@op>,</@op> sessionApi);
<@comment>// Login resource</@comment>
httpServer<@op>.</@op>route(
<@string>"/api/login"</@string><@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Post<@op>,</@op>
<@op>[</@op><@op>&</@op>sessionApi<@op>]</@op>(<@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) { <@keyword>return</@keyword> sessionApi<@op>.</@op>login(request); });
httpServer<@op>.</@op>route(<@string>"/api/register"</@string><@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Post<@op>,</@op>
<@op>[</@op><@op>&</@op>sessionApi<@op>]</@op>(<@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) {
<@keyword>return</@keyword> sessionApi<@op>.</@op>registerSession(request);
});
httpServer<@op>.</@op>route(<@string>"/api/logout"</@string><@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Post<@op>,</@op>
<@op>[</@op><@op>&</@op>sessionApi<@op>]</@op>(<@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>request) {
<@keyword>return</@keyword> sessionApi<@op>.</@op>logout(request);
});
<@comment>// Images resource</@comment>
httpServer<@op>.</@op>route(<@string>"/img/faces/<arg>-image.jpg"</@string><@op>,</@op> <@type>QHttpServerRequest</@type><@op>::</@op>Method<@op>::</@op>Get<@op>,</@op>
<@op>[</@op><@op>]</@op>(<@type>qint64</@type> imageId<@op>,</@op> <@keyword>const</@keyword> <@type>QHttpServerRequest</@type> <@op>&</@op>) {
<@keyword>return</@keyword> <@type>QHttpServerResponse</@type><@op>::</@op>fromFile(
<@type>QString</@type>(<@string>":/assets/img/%1-image.jpg"</@string>)<@op>.</@op>arg(imageId));
});
<@keyword>auto</@keyword> tcpserver <@op>=</@op> std<@op>::</@op>make_unique<@op><</@op><@type>QTcpServer</@type><@op>></@op>();
<@keyword>if</@keyword> (<@op>!</@op>tcpserver<@op>-</@op><@op>></@op>listen(<@type>QHostAddress</@type><@op>::</@op>Any<@op>,</@op> portArg) <@op>|</@op><@op>|</@op> <@op>!</@op>httpServer<@op>.</@op>bind(tcpserver<@op>.</@op>get())) {
<@func target="qDebug()">qDebug</@func>() <@op><</@op><@op><</@op> <@type>QCoreApplication</@type><@op>::</@op>translate(<@string>"QHttpServerExample"</@string><@op>,</@op>
<@string>"Server failed to listen on a port."</@string>);
<@keyword>return</@keyword> <@number>0</@number>;
}
<@type>quint16</@type> port <@op>=</@op> tcpserver<@op>-</@op><@op>></@op>serverPort();
tcpserver<@op>.</@op>release();
<@func target="qDebug()">qDebug</@func>() <@op><</@op><@op><</@op> <@type>QCoreApplication</@type><@op>::</@op>translate(
<@string>"QHttpServerExample"</@string><@op>,</@op>
<@string>"Running on http://127.0.0.1:%1/ (Press CTRL+C to quit)"</@string>)
<@op>.</@op>arg(port);
<@keyword>return</@keyword> app<@op>.</@op>exec();
}