yacreader/YACReaderLibrary/server/yacreader_http_server.cpp
2023-06-18 10:42:38 +02:00

187 lines
6.0 KiB
C++

/**
@file
@author Stefan Frings
*/
#include "static.h"
#include "yacreader_http_server.h"
// #include "dualfilelogger.h"
#include "httplistener.h"
#include "requestmapper.h"
#include "staticfilecontroller.h"
#include "yacreader_global.h"
#include <QDir>
#include <QCoreApplication>
/** Name of this application */
#define APPNAME "YACReaderLibrary"
/** Publisher of this application */
#define ORGANISATION "YACReader"
/** Short description of this application */
#define DESCRIPTION "Comic reader and organizer"
using stefanfrings::HttpListener;
using stefanfrings::HttpRequest;
using stefanfrings::HttpResponse;
using stefanfrings::HttpSessionStore;
using stefanfrings::StaticFileController;
using stefanfrings::TemplateCache;
void YACReaderHttpServer::start(quint16 port)
{
// Initialize the core application
QCoreApplication *app = QCoreApplication::instance();
QString configFileName = YACReader::getSettingsPath() + "/" + QCoreApplication::applicationName() + ".ini";
// Configure template loader and cache
auto templateSettings = new QSettings(configFileName, QSettings::IniFormat, app);
templateSettings->beginGroup("templates");
if (templateSettings->value("cacheSize").isNull())
templateSettings->setValue("cacheSize", "160000");
QString baseTemplatePath = QString("./server/templates");
QString templatePath;
#if defined Q_OS_UNIX && !defined Q_OS_MACOS
templatePath = QFileInfo(QString(DATADIR) + "/yacreader", baseTemplatePath).absoluteFilePath();
#else
templatePath = QFileInfo(QCoreApplication::applicationDirPath(), baseTemplatePath).absoluteFilePath();
#endif
if (!templateSettings->contains("path"))
templateSettings->setValue("path", templatePath);
Static::templateLoader = new TemplateCache(templateSettings, app);
// Configure session store
auto sessionSettings = new QSettings(configFileName, QSettings::IniFormat, app);
sessionSettings->beginGroup("sessions");
if (sessionSettings->value("expirationTime").isNull())
sessionSettings->setValue("expirationTime", 864000000);
Static::sessionStore = new HttpSessionStore(sessionSettings, app);
Static::yacreaderSessionStore = new YACReaderHttpSessionStore(Static::sessionStore, app);
// Configure static file controller
auto fileSettings = new QSettings(configFileName, QSettings::IniFormat, app);
fileSettings->beginGroup("docroot");
QString basedocroot = "./server/docroot";
QString docroot;
#if defined Q_OS_UNIX && !defined Q_OS_MACOS
QFileInfo configFile(QString(DATADIR) + "/yacreader");
docroot = QFileInfo(QString(DATADIR) + "/yacreader", basedocroot).absoluteFilePath();
#else
QFileInfo configFile(QCoreApplication::applicationDirPath());
docroot = QFileInfo(QCoreApplication::applicationDirPath(), basedocroot).absoluteFilePath();
#endif
if (!fileSettings->contains("path"))
fileSettings->setValue("path", docroot);
Static::staticFileController = new StaticFileController(fileSettings, app);
// Configure and start the TCP listener
qDebug("ServiceHelper: Starting service");
auto listenerSettings = new QSettings(configFileName, QSettings::IniFormat, app);
listenerSettings->beginGroup("listener");
if (listenerSettings->value("maxRequestSize").isNull())
listenerSettings->setValue("maxRequestSize", "32000000");
if (listenerSettings->value("maxMultiPartSize").isNull())
listenerSettings->setValue("maxMultiPartSize", "32000000");
if (listenerSettings->value("cleanupInterval").isNull())
listenerSettings->setValue("cleanupInterval", 10000);
if (listenerSettings->value("minThreads").isNull())
listenerSettings->setValue("maxThreads", 1000);
if (listenerSettings->value("minThreads").isNull())
listenerSettings->setValue("minThreads", 50);
if (listenerSettings->value("port").isNull())
listenerSettings->setValue("port", 8080);
// start with a temporary port
if (port != 0) {
// cache saved port
if (!listenerSettings->contains("cachedPort")) {
listenerSettings->setValue("cachedPort", listenerSettings->value("port").toInt());
}
listenerSettings->setValue("port", port);
} else {
// restore saved port
if (listenerSettings->contains("cachedPort")) {
listenerSettings->setValue("port", listenerSettings->value("cachedPort"));
listenerSettings->remove("cachedPort");
}
}
// test if port is working
{
QTcpServer testServer;
if (!testServer.listen(QHostAddress::Any, listenerSettings->value("port").toInt())) {
qDebug("Port is busy.");
// get random port
testServer.listen(QHostAddress::Any, 0);
listenerSettings->setValue("port", testServer.serverPort());
}
testServer.close();
}
auto requestMapper = new RequestMapper(app);
listener = new HttpListener(listenerSettings, requestMapper, app);
connect(requestMapper, &RequestMapper::comicUpdated, this, &YACReaderHttpServer::comicUpdated);
connect(requestMapper, &RequestMapper::clientSync, this, &YACReaderHttpServer::clientSync);
if (listener->isListening()) {
qDebug("ServiceHelper: Service has started");
} else {
qDebug("ServiceHelper: Could not launch service");
}
}
void YACReaderHttpServer::stop()
{
qDebug("ServiceHelper: Service has been stopped");
// QCoreApplication destroys all objects that have been created in start().
if (listener != nullptr) {
listener->close();
delete listener;
listener = nullptr;
}
}
bool YACReaderHttpServer::isRunning()
{
if (listener == nullptr) {
return false;
}
return listener->isListening();
}
YACReaderHttpServer::YACReaderHttpServer()
: QObject(nullptr), listener(nullptr)
{
}
QString YACReaderHttpServer::getPort()
{
if (listener == nullptr) {
return "-1";
}
return QString("%1").arg(listener->serverPort());
}