From b2756c92413fa6bb76ed01ed863ce597354f722d Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 16 Apr 2018 17:08:03 +0200 Subject: [PATCH] make the REST server optional and disabled by default Also fixes an issue where the REST server would sometimes try to send the reply to the wrong WebServer instance --- libnymea-core/nymeaconfiguration.cpp | 5 +++++ libnymea-core/nymeaconfiguration.h | 1 + libnymea-core/rest/restserver.cpp | 32 +++++++++++++++------------- libnymea-core/rest/restserver.h | 3 +-- libnymea-core/webserver.cpp | 16 ++++++++++---- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/libnymea-core/nymeaconfiguration.cpp b/libnymea-core/nymeaconfiguration.cpp index 6d4670bb..ff971d81 100644 --- a/libnymea-core/nymeaconfiguration.cpp +++ b/libnymea-core/nymeaconfiguration.cpp @@ -114,6 +114,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) : insecureConfig.sslEnabled = false; insecureConfig.authenticationEnabled = false; insecureConfig.publicFolder = defaultWebserverPublicFolderPath(); + insecureConfig.restServerEnabled = false; m_webServerConfigs[insecureConfig.id] = insecureConfig; storeWebServerConfig(insecureConfig); @@ -124,6 +125,7 @@ NymeaConfiguration::NymeaConfiguration(QObject *parent) : secureConfig.sslEnabled = true; secureConfig.authenticationEnabled = false; secureConfig.publicFolder = defaultWebserverPublicFolderPath(); + secureConfig.restServerEnabled = false; m_webServerConfigs[secureConfig.id] = secureConfig; storeWebServerConfig(secureConfig); } @@ -269,6 +271,7 @@ void NymeaConfiguration::setWebServerConfiguration(const WebServerConfiguration settings.beginGroup("WebServer"); settings.beginGroup(config.id); settings.setValue("publicFolder", config.publicFolder); + settings.setValue("restServerEnabled", config.restServerEnabled); settings.endGroup(); settings.endGroup(); @@ -479,6 +482,7 @@ void NymeaConfiguration::storeWebServerConfig(const WebServerConfiguration &conf settings.beginGroup("WebServer"); settings.beginGroup(config.id); settings.setValue("publicFolder", config.publicFolder); + settings.setValue("restServerEnabled", config.restServerEnabled); settings.endGroup(); settings.endGroup(); } @@ -495,6 +499,7 @@ WebServerConfiguration NymeaConfiguration::readWebServerConfig(const QString &id config.sslEnabled = settings.value("sslEnabled", true).toBool(); config.authenticationEnabled = settings.value("authenticationEnabled", true).toBool(); config.publicFolder = settings.value("publicFolder").toString(); + config.restServerEnabled = settings.value("restServerEnabled", false).toBool(); settings.endGroup(); settings.endGroup(); return config; diff --git a/libnymea-core/nymeaconfiguration.h b/libnymea-core/nymeaconfiguration.h index f6e519df..b5514847 100644 --- a/libnymea-core/nymeaconfiguration.h +++ b/libnymea-core/nymeaconfiguration.h @@ -53,6 +53,7 @@ class WebServerConfiguration: public ServerConfiguration { public: QString publicFolder; + bool restServerEnabled = false; }; class NymeaConfiguration : public QObject diff --git a/libnymea-core/rest/restserver.cpp b/libnymea-core/rest/restserver.cpp index 70598650..4428f6c1 100644 --- a/libnymea-core/rest/restserver.cpp +++ b/libnymea-core/rest/restserver.cpp @@ -46,8 +46,7 @@ namespace nymeaserver { /*! Constructs a \l{RestServer} with the given \a sslConfiguration and \a parent. */ RestServer::RestServer(const QSslConfiguration &sslConfiguration, QObject *parent) : - QObject(parent), - m_webserver(0) + QObject(parent) { Q_UNUSED(sslConfiguration) @@ -61,12 +60,10 @@ RestServer::RestServer(const QSslConfiguration &sslConfiguration, QObject *paren */ void RestServer::registerWebserver(WebServer *webServer) { - m_webserver = webServer; - connect(m_webserver, &WebServer::clientConnected, this, &RestServer::clientConnected); - connect(m_webserver, &WebServer::clientDisconnected, this, &RestServer::clientDisconnected); - connect(m_webserver, &WebServer::httpRequestReady, this, &RestServer::processHttpRequest); - - QMetaObject::invokeMethod(m_webserver, "startServer", Qt::QueuedConnection); + connect(webServer, &WebServer::clientConnected, this, &RestServer::clientConnected); + connect(webServer, &WebServer::clientDisconnected, this, &RestServer::clientDisconnected); + connect(webServer, &WebServer::httpRequestReady, this, &RestServer::processHttpRequest); + QMetaObject::invokeMethod(webServer, "startServer", Qt::QueuedConnection); } void RestServer::setup() @@ -89,12 +86,13 @@ void RestServer::setup() void RestServer::clientConnected(const QUuid &clientId) { - m_clientList.append(clientId); + WebServer *webserver = dynamic_cast(sender()); + m_clientList.insert(clientId, webserver); } void RestServer::clientDisconnected(const QUuid &clientId) { - m_clientList.removeAll(clientId); + m_clientList.take(clientId); } void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &request) @@ -102,11 +100,14 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re QStringList urlTokens = request.url().path().split("/"); urlTokens.removeAll(QString()); + WebServer *webserver = dynamic_cast(sender()); + Q_ASSERT(webserver); + // check token count if (urlTokens.count() < 3) { HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); reply->setClientId(clientId); - m_webserver->sendHttpReply(reply); + webserver->sendHttpReply(reply); reply->deleteLater(); return; } @@ -116,7 +117,7 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re if (!m_resources.contains(resourceName)) { HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); reply->setClientId(clientId); - m_webserver->sendHttpReply(reply); + webserver->sendHttpReply(reply); reply->deleteLater(); return; } @@ -125,7 +126,7 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re if (request.method() == HttpRequest::Options && urlTokens.count() == 3) { HttpReply *reply = RestResource::createCorsSuccessReply(); reply->setClientId(clientId); - m_webserver->sendHttpReply(reply); + webserver->sendHttpReply(reply); reply->deleteLater(); return; } @@ -141,7 +142,7 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re reply->startWait(); return; } - m_webserver->sendHttpReply(reply); + webserver->sendHttpReply(reply); reply->deleteLater(); } @@ -171,7 +172,8 @@ void RestServer::asyncReplyFinished() qCWarning(dcWebServer) << "Client for async reply not longer connected."; } else { reply->setClientId(clientId); - m_webserver->sendHttpReply(reply); + WebServer *webserver = m_clientList.value(clientId); + webserver->sendHttpReply(reply); } reply->deleteLater(); } diff --git a/libnymea-core/rest/restserver.h b/libnymea-core/rest/restserver.h index f854c1a5..aa849430 100644 --- a/libnymea-core/rest/restserver.h +++ b/libnymea-core/rest/restserver.h @@ -48,8 +48,7 @@ public: void registerWebserver(WebServer *webServer); private: - WebServer *m_webserver; - QList m_clientList; + QHash m_clientList; QHash m_resources; QHash m_asyncReplies; diff --git a/libnymea-core/webserver.cpp b/libnymea-core/webserver.cpp index 6ab6f992..16894264 100644 --- a/libnymea-core/webserver.cpp +++ b/libnymea-core/webserver.cpp @@ -106,9 +106,8 @@ WebServer::WebServer(const WebServerConfiguration &configuration, const QSslConf { if (QCoreApplication::instance()->organizationName() == "nymea-test") { m_configuration.publicFolder = QCoreApplication::applicationDirPath(); - qCWarning(dcWebServer) << "Using public folder" << QDir(m_configuration.publicFolder).canonicalPath(); } - qCDebug(dcWebServer) << "Using public folder" << QDir(m_configuration.publicFolder).canonicalPath(); + qCDebug(dcWebServer) << "Starting WebServer. Interface:" << m_configuration.address << "Port:" << m_configuration.port << "SSL:" << m_configuration.sslEnabled << "AUTH:" << m_configuration.authenticationEnabled << "Public folder:" << QDir(m_configuration.publicFolder).canonicalPath(); m_avahiService = new QtAvahiService(this); connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &WebServer::onAvahiServiceStateChanged); @@ -351,8 +350,17 @@ void WebServer::readClient() // Verify API query if (request.url().path().startsWith("/api/v1")) { - emit httpRequestReady(clientId, request); - return; + if (m_configuration.restServerEnabled) { + emit httpRequestReady(clientId, request); + return; + } else { + qCWarning(dcWebServer()) << "The REST server is disabled. You can enable it by adding \'restServerEnabled=true\' in the WebServer section of the nymead.conf file."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setClientId(clientId); + sendHttpReply(reply); + reply->deleteLater(); + return; + } } // Check icon call