Add debug server interface
This commit is contained in:
parent
aede5f2afa
commit
5e69772035
7
debian/changelog
vendored
7
debian/changelog
vendored
@ -1,3 +1,10 @@
|
||||
guh (0.8.3) xenial; urgency=medium
|
||||
|
||||
* Add debug server
|
||||
* Add interfaces
|
||||
|
||||
-- Simon Stürz <simon.stuerz@guh.io> Thu, 08 Feb 2018 23:10:42 +0100
|
||||
|
||||
guh (0.8.2) xenial; urgency=medium
|
||||
|
||||
* New hardware manager api
|
||||
|
||||
2
guh.pri
2
guh.pri
@ -6,7 +6,7 @@ GUH_PLUGINS_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/gu
|
||||
|
||||
# define protocol versions
|
||||
JSON_PROTOCOL_VERSION_MAJOR=1
|
||||
JSON_PROTOCOL_VERSION_MINOR=1
|
||||
JSON_PROTOCOL_VERSION_MINOR=2
|
||||
REST_API_VERSION=1
|
||||
|
||||
DEFINES += GUH_VERSION_STRING=\\\"$${GUH_VERSION_STRING}\\\" \
|
||||
|
||||
560
libguh-core/debugserverhandler.cpp
Normal file
560
libguh-core/debugserverhandler.cpp
Normal file
@ -0,0 +1,560 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "guhcore.h"
|
||||
#include "httpreply.h"
|
||||
#include "guhsettings.h"
|
||||
#include "httprequest.h"
|
||||
#include "loggingcategories.h"
|
||||
#include "debugserverhandler.h"
|
||||
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace guhserver {
|
||||
|
||||
DebugServerHandler::DebugServerHandler(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray DebugServerHandler::createDebugXmlDocument()
|
||||
{
|
||||
QByteArray data;
|
||||
QXmlStreamWriter writer(&data);
|
||||
writer.setAutoFormatting(true);
|
||||
writer.writeStartDocument("1.0");
|
||||
writer.writeProcessingInstruction("DOCUMENT", "html");
|
||||
writer.writeComment("Auto generated html page from nymea");
|
||||
writer.writeStartElement("html");
|
||||
writer.writeAttribute("lang", GuhCore::instance()->configuration()->locale().name());
|
||||
|
||||
writer.writeStartElement("head");
|
||||
|
||||
writer.writeEmptyElement("meta");
|
||||
writer.writeAttribute("http-equiv", "Content-Type");
|
||||
writer.writeAttribute("content", "text/html; charset=utf-8");
|
||||
writer.writeTextElement("title", QCoreApplication::translate("main", "Debug nymea"));
|
||||
|
||||
writer.writeEndElement(); // head
|
||||
|
||||
writer.writeStartElement("body");
|
||||
|
||||
// Welcome section
|
||||
writer.writeTextElement("h1", QCoreApplication::translate("main", "nymea debug interface"));
|
||||
writer.writeEmptyElement("hr");
|
||||
writer.writeTextElement("p", QCoreApplication::translate("main", "Welcome to the debug interface. This debug interface was designed to provide an easy possibility to get helpful information about the running nymea server. This interfaces provides read only options and is disabled by default."));
|
||||
|
||||
writer.writeEmptyElement("hr");
|
||||
writer.writeTextElement("h3", QCoreApplication::translate("main", "Warning"));
|
||||
writer.writeTextElement("p", QCoreApplication::translate("main", "Be aware that this debug interface is a security breach and offers access to the system log and therefore to possibly sensible data. If you are not using the debug tools, than you should disable this debug server."));
|
||||
writer.writeTextElement("p", QCoreApplication::translate("main", "The debug server can be disabled by changing the the value \"debugServerEnabled=false\" in the \"guhd\" section of %1 or using the API method \"Configuration.SetDebugServerEnabled\".").arg(GuhSettings(GuhSettings::SettingsRoleGlobal).fileName()));
|
||||
writer.writeEmptyElement("hr");
|
||||
|
||||
// System information section
|
||||
writer.writeTextElement("h2", QCoreApplication::translate("main", "Server information"));
|
||||
writer.writeEmptyElement("hr");
|
||||
|
||||
writer.writeStartElement("table");
|
||||
writer.writeAttribute("width", "100%");
|
||||
writer.writeAttribute("border", "1");
|
||||
|
||||
writer.writeStartElement("col");
|
||||
writer.writeAttribute("align", "left");
|
||||
writer.writeEndElement(); // col
|
||||
|
||||
writer.writeStartElement("col");
|
||||
writer.writeAttribute("align", "right");
|
||||
writer.writeEndElement(); // col
|
||||
|
||||
QString userName = qgetenv("USER");
|
||||
if (userName.isEmpty())
|
||||
userName = qgetenv("USERNAME");
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "User"));
|
||||
writer.writeTextElement("td", userName);
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Compiled with Qt version"));
|
||||
writer.writeTextElement("td", QT_VERSION_STR);
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Qt runtime version"));
|
||||
writer.writeTextElement("td", qVersion());
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Command"));
|
||||
writer.writeTextElement("td", QCoreApplication::arguments().join(' '));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
if (!qgetenv("SNAP").isEmpty()) {
|
||||
// Note: http://snapcraft.io/docs/reference/env
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Snap name"));
|
||||
writer.writeTextElement("td", qgetenv("SNAP_NAME"));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Snap version"));
|
||||
writer.writeTextElement("td", qgetenv("SNAP_VERSION"));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Snap directory"));
|
||||
writer.writeTextElement("td", qgetenv("SNAP"));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Snap application data"));
|
||||
writer.writeTextElement("td", qgetenv("SNAP_DATA"));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Snap user data"));
|
||||
writer.writeTextElement("td", qgetenv("SNAP_USER_DATA"));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Snap common data"));
|
||||
writer.writeTextElement("td", qgetenv("SNAP_COMMON"));
|
||||
writer.writeEndElement(); // tr
|
||||
}
|
||||
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Server name"));
|
||||
writer.writeTextElement("td", GuhCore::instance()->configuration()->serverName());
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Server version"));
|
||||
writer.writeTextElement("td", GUH_VERSION_STRING);
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "JSON-RPC version"));
|
||||
writer.writeTextElement("td", JSON_PROTOCOL_VERSION);
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Language"));
|
||||
writer.writeTextElement("td", GuhCore::instance()->configuration()->locale().name() + " (" + GuhCore::instance()->configuration()->locale().nativeCountryName() + " - " + GuhCore::instance()->configuration()->locale().nativeLanguageName() + ")");
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Timezone"));
|
||||
writer.writeTextElement("td", QString::fromUtf8(GuhCore::instance()->configuration()->timeZone()));
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Server UUID"));
|
||||
writer.writeTextElement("td", GuhCore::instance()->configuration()->serverUuid().toString());
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Settings path"));
|
||||
writer.writeTextElement("td", GuhSettings(GuhSettings::SettingsRoleGlobal).settingsPath());
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Translations path"));
|
||||
writer.writeTextElement("td", GuhSettings(GuhSettings::SettingsRoleGlobal).translationsPath());
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Log database"));
|
||||
writer.writeTextElement("td", GuhSettings(GuhSettings::SettingsRoleGlobal).logPath());
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
for (int i = 0; i < GuhCore::instance()->deviceManager()->pluginSearchDirs().count(); i++) {
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
if (i == 0) {
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Plugin paths"));
|
||||
} else {
|
||||
writer.writeTextElement("th", "");
|
||||
}
|
||||
writer.writeTextElement("td", GuhCore::instance()->deviceManager()->pluginSearchDirs().at(i));
|
||||
}
|
||||
|
||||
writer.writeEndElement(); // table
|
||||
|
||||
|
||||
// Downloads section
|
||||
writer.writeEmptyElement("hr");
|
||||
writer.writeTextElement("h2", QCoreApplication::translate("main", "Downloads"));
|
||||
writer.writeEmptyElement("hr");
|
||||
|
||||
// Logs download section
|
||||
writer.writeTextElement("h3", QCoreApplication::translate("main", "Logs"));
|
||||
|
||||
writer.writeStartElement("table");
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Log database"));
|
||||
writer.writeStartElement("td");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("method", "get");
|
||||
writer.writeAttribute("action", "/debug/logdb.sql");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("type", "submit");
|
||||
writer.writeCharacters(QCoreApplication::translate("main", "Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // td
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Syslog"));
|
||||
writer.writeStartElement("td");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("method", "get");
|
||||
writer.writeAttribute("action", "/debug/syslog");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("type", "submit");
|
||||
writer.writeCharacters(QCoreApplication::translate("main", "Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // td
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
// TODO: offer logfile download if specified in the command line options
|
||||
|
||||
writer.writeEndElement(); // table
|
||||
|
||||
|
||||
// Settings download section
|
||||
writer.writeTextElement("h3", QCoreApplication::translate("main", "Settings"));
|
||||
|
||||
writer.writeStartElement("table");
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Guhd settings"));
|
||||
writer.writeStartElement("td");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("method", "get");
|
||||
writer.writeAttribute("action", "/debug/settings/guhd");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("type", "submit");
|
||||
writer.writeCharacters(QCoreApplication::translate("main", "Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // td
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Device settings"));
|
||||
writer.writeStartElement("td");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("method", "get");
|
||||
writer.writeAttribute("action", "/debug/settings/devices");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("type", "submit");
|
||||
writer.writeCharacters(QCoreApplication::translate("main", "Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // td
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Device state settings"));
|
||||
writer.writeStartElement("td");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("method", "get");
|
||||
writer.writeAttribute("action", "/debug/settings/devicestates");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("type", "submit");
|
||||
writer.writeCharacters(QCoreApplication::translate("main", "Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // td
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
|
||||
writer.writeStartElement("tr");
|
||||
writer.writeTextElement("th", QCoreApplication::translate("main", "Rules settings"));
|
||||
writer.writeStartElement("td");
|
||||
writer.writeStartElement("form");
|
||||
writer.writeAttribute("method", "get");
|
||||
writer.writeAttribute("action", "/debug/settings/rules");
|
||||
writer.writeStartElement("button");
|
||||
writer.writeAttribute("type", "submit");
|
||||
writer.writeCharacters(QCoreApplication::translate("main", "Download"));
|
||||
writer.writeEndElement(); // button
|
||||
writer.writeEndElement(); // form
|
||||
writer.writeEndElement(); // td
|
||||
writer.writeEndElement(); // tr
|
||||
|
||||
writer.writeEndElement(); // table
|
||||
|
||||
writer.writeEmptyElement("hr");
|
||||
|
||||
writer.writeStartElement("footer");
|
||||
writer.writeTextElement("p", QString("Copyright %1 2018 guh GmbH.").arg(QChar(0xA9)));
|
||||
writer.writeTextElement("p", QCoreApplication::translate("main", "Released under the GNU GENERAL PUBLIC LICENSE Version 2."));
|
||||
writer.writeEndElement(); // footer
|
||||
|
||||
writer.writeEndElement(); // body
|
||||
|
||||
writer.writeEndElement(); // html
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
QByteArray DebugServerHandler::createErrorXmlDocument(HttpReply::HttpStatusCode statusCode, const QString &errorMessage)
|
||||
{
|
||||
QByteArray data;
|
||||
QXmlStreamWriter writer(&data);
|
||||
writer.setAutoFormatting(true);
|
||||
writer.writeStartDocument("1.0");
|
||||
writer.writeComment("Live generated html page from nymea");
|
||||
writer.writeStartElement("html");
|
||||
writer.writeAttribute("lang", GuhCore::instance()->configuration()->locale().name());
|
||||
|
||||
writer.writeStartElement("head");
|
||||
|
||||
writer.writeEmptyElement("meta");
|
||||
writer.writeAttribute("http-equiv", "Content-Type");
|
||||
writer.writeAttribute("content", "text/html; charset=utf-8");
|
||||
writer.writeTextElement("title", QCoreApplication::translate("main", "Debug nymea"));
|
||||
|
||||
writer.writeEndElement(); // head
|
||||
|
||||
writer.writeStartElement("body");
|
||||
|
||||
writer.writeTextElement("h1", QCoreApplication::translate("main", "Error") + QString(" %1").arg(static_cast<int>(statusCode)));
|
||||
writer.writeEmptyElement("hr");
|
||||
|
||||
writer.writeTextElement("p", errorMessage);
|
||||
|
||||
writer.writeEmptyElement("hr");
|
||||
|
||||
writer.writeStartElement("footer");
|
||||
writer.writeTextElement("p", QString("Copyright %1 2018 guh GmbH.").arg(QChar(0xA9)));
|
||||
writer.writeTextElement("p", QCoreApplication::translate("main", "Released under the GNU GENERAL PUBLIC LICENSE Version 2."));
|
||||
writer.writeEndElement(); // footer
|
||||
|
||||
writer.writeEndElement(); // body
|
||||
|
||||
writer.writeEndElement(); // html
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath)
|
||||
{
|
||||
qCDebug(dcWebServer()) << "Debug request for" << requestPath;
|
||||
|
||||
// Check if this is a logdb requested
|
||||
if (requestPath.startsWith("/debug/logdb.sql")) {
|
||||
qCDebug(dcWebServer()) << "Loading" << GuhSettings::logPath();
|
||||
QFile logDatabaseFile(GuhSettings::logPath());
|
||||
if (!logDatabaseFile.exists()) {
|
||||
qCWarning(dcWebServer()) << "Could not read log database file for debug download" << GuhSettings::logPath() << "file does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not find file") + " " + logDatabaseFile.fileName()));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!logDatabaseFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcWebServer()) << "Could not read log database file for debug download" << GuhSettings::logPath();
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not open file") + " " + logDatabaseFile.fileName()));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray logDatabaseRawData = logDatabaseFile.readAll();
|
||||
logDatabaseFile.close();
|
||||
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "application/sql");
|
||||
reply->setPayload(logDatabaseRawData);
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
// Check if this is a syslog requested
|
||||
if (requestPath.startsWith("/debug/syslog")) {
|
||||
QString syslogFileName = "/var/log/syslog";
|
||||
qCDebug(dcWebServer()) << "Loading" << syslogFileName;
|
||||
QFile syslogFile(syslogFileName);
|
||||
if (!syslogFile.exists()) {
|
||||
qCWarning(dcWebServer()) << "Could not read log database file for debug download" << syslogFileName << "file does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not find file") + " " + syslogFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!syslogFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcWebServer()) << "Could not read syslog file for debug download" << syslogFileName;
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not open file") + " " + syslogFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray syslogFileData = syslogFile.readAll();
|
||||
syslogFile.close();
|
||||
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
|
||||
reply->setPayload(syslogFileData);
|
||||
return reply;
|
||||
}
|
||||
|
||||
// Check if this is a settings request
|
||||
if (requestPath.startsWith("/debug/settings")) {
|
||||
if (requestPath.startsWith("/debug/settings/devices")) {
|
||||
QString settingsFileName = GuhSettings(GuhSettings::SettingsRoleDevices).fileName();
|
||||
qCDebug(dcWebServer()) << "Loading" << settingsFileName;
|
||||
QFile settingsFile(settingsFileName);
|
||||
if (!settingsFile.exists()) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not find file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!settingsFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName;
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not open file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray settingsFileData = settingsFile.readAll();
|
||||
settingsFile.close();
|
||||
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
|
||||
reply->setPayload(settingsFileData);
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (requestPath.startsWith("/debug/settings/rules")) {
|
||||
QString settingsFileName = GuhSettings(GuhSettings::SettingsRoleRules).fileName();
|
||||
qCDebug(dcWebServer()) << "Loading" << settingsFileName;
|
||||
QFile settingsFile(settingsFileName);
|
||||
if (!settingsFile.exists()) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not find file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!settingsFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName;
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not open file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray settingsFileData = settingsFile.readAll();
|
||||
settingsFile.close();
|
||||
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
|
||||
reply->setPayload(settingsFileData);
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (requestPath.startsWith("/debug/settings/guhd")) {
|
||||
QString settingsFileName = GuhSettings(GuhSettings::SettingsRoleGlobal).fileName();
|
||||
qCDebug(dcWebServer()) << "Loading" << settingsFileName;
|
||||
QFile settingsFile(settingsFileName);
|
||||
if (!settingsFile.exists()) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not find file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!settingsFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName;
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not open file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray settingsFileData = settingsFile.readAll();
|
||||
settingsFile.close();
|
||||
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
|
||||
reply->setPayload(settingsFileData);
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (requestPath.startsWith("/debug/settings/devicestates")) {
|
||||
QString settingsFileName = GuhSettings(GuhSettings::SettingsRoleDeviceStates).fileName();
|
||||
qCDebug(dcWebServer()) << "Loading" << settingsFileName;
|
||||
QFile settingsFile(settingsFileName);
|
||||
if (!settingsFile.exists()) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not find file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
if (!settingsFile.open(QFile::ReadOnly)) {
|
||||
qCWarning(dcWebServer()) << "Could not read file for debug download" << settingsFileName;
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, QCoreApplication::translate("main", "Could not open file") + " " + settingsFileName));
|
||||
return reply;
|
||||
}
|
||||
|
||||
QByteArray settingsFileData = settingsFile.readAll();
|
||||
settingsFile.close();
|
||||
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
|
||||
reply->setPayload(settingsFileData);
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(dcWebServer()) << "Create debug interface page";
|
||||
|
||||
// Fallback default debug page
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html");
|
||||
reply->setPayload(createDebugXmlDocument());
|
||||
return reply;
|
||||
}
|
||||
|
||||
}
|
||||
46
libguh-core/debugserverhandler.h
Normal file
46
libguh-core/debugserverhandler.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
* Guh is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, version 2 of the License. *
|
||||
* *
|
||||
* Guh is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef DEBUGSERVERHANDLER_H
|
||||
#define DEBUGSERVERHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "httpreply.h"
|
||||
|
||||
namespace guhserver {
|
||||
|
||||
class DebugServerHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DebugServerHandler(QObject *parent = nullptr);
|
||||
|
||||
HttpReply *processDebugRequest(const QString &requestPath);
|
||||
|
||||
private:
|
||||
QByteArray createDebugXmlDocument();
|
||||
QByteArray createErrorXmlDocument(HttpReply::HttpStatusCode statusCode, const QString &errorMessage);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DEBUGSERVERHANDLER_H
|
||||
@ -56,6 +56,7 @@ GuhConfiguration::GuhConfiguration(QObject *parent) :
|
||||
setLocale(locale());
|
||||
setBluetoothServerEnabled(bluetoothServerEnabled());
|
||||
setSslCertificate(sslCertificate(), sslCertificateKey());
|
||||
setDebugServerEnabled(debugServerEnabled());
|
||||
|
||||
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
|
||||
|
||||
@ -387,6 +388,25 @@ void GuhConfiguration::setSslCertificate(const QString &sslCertificate, const QS
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
bool GuhConfiguration::debugServerEnabled() const
|
||||
{
|
||||
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
|
||||
settings.beginGroup("guhd");
|
||||
return settings.value("debugServerEnabled", false).toBool();
|
||||
}
|
||||
|
||||
void GuhConfiguration::setDebugServerEnabled(bool enabled)
|
||||
{
|
||||
qCDebug(dcApplication()) << "Configuration: Set debug server" << (enabled ? "enabled" : "disabled");
|
||||
if (debugServerEnabled() != enabled) {
|
||||
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
|
||||
settings.beginGroup("guhd");
|
||||
settings.setValue("debugServerEnabled", enabled);
|
||||
settings.endGroup();
|
||||
emit debugServerEnabledChanged(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void GuhConfiguration::setServerUuid(const QUuid &uuid)
|
||||
{
|
||||
qCDebug(dcApplication()) << "Configuration: Server uuid:" << uuid.toString();
|
||||
|
||||
@ -90,6 +90,10 @@ public:
|
||||
QString sslCertificateKey() const;
|
||||
void setSslCertificate(const QString &sslCertificate, const QString &sslCertificateKey);
|
||||
|
||||
// Debug server
|
||||
bool debugServerEnabled() const;
|
||||
void setDebugServerEnabled(bool enabled);
|
||||
|
||||
// TCP server
|
||||
QHash<QString, ServerConfiguration> tcpServerConfigurations() const;
|
||||
void setTcpServerConfiguration(const ServerConfiguration &config);
|
||||
@ -148,6 +152,7 @@ signals:
|
||||
|
||||
void bluetoothServerEnabledChanged();
|
||||
void cloudEnabledChanged(bool enabled);
|
||||
void debugServerEnabledChanged(bool enabled);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -461,6 +461,11 @@ CloudManager *GuhCore::cloudManager() const
|
||||
return m_cloudManager;
|
||||
}
|
||||
|
||||
DebugServerHandler *GuhCore::debugServerHandler() const
|
||||
{
|
||||
return m_debugServerHandler;
|
||||
}
|
||||
|
||||
|
||||
/*! Constructs GuhCore with the given \a parent. This is private.
|
||||
Use \l{GuhCore::instance()} to access the single instance.*/
|
||||
@ -495,10 +500,12 @@ void GuhCore::init() {
|
||||
qCDebug(dcApplication) << "Creating Server Manager";
|
||||
m_serverManager = new ServerManager(m_configuration, this);
|
||||
|
||||
// Create the NetworkManager
|
||||
qCDebug(dcApplication) << "Creating Network Manager";
|
||||
m_networkManager = new NetworkManager(this);
|
||||
|
||||
qCDebug(dcApplication) << "Creating Debug Server Handler";
|
||||
m_debugServerHandler = new DebugServerHandler(this);
|
||||
|
||||
qCDebug(dcApplication) << "Creating Cloud Manager";
|
||||
m_cloudManager = new CloudManager(m_networkManager, this);
|
||||
m_cloudManager->setDeviceId(m_configuration->serverUuid());
|
||||
|
||||
@ -38,6 +38,8 @@
|
||||
#include "time/timemanager.h"
|
||||
#include "hardwaremanagerimplementation.h"
|
||||
|
||||
#include "debugserverhandler.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Device;
|
||||
@ -80,6 +82,7 @@ public:
|
||||
NetworkManager *networkManager() const;
|
||||
UserManager *userManager() const;
|
||||
CloudManager *cloudManager() const;
|
||||
DebugServerHandler *debugServerHandler() const;
|
||||
|
||||
static QStringList getAvailableLanguages();
|
||||
|
||||
@ -115,6 +118,7 @@ private:
|
||||
TimeManager *m_timeManager;
|
||||
CloudManager *m_cloudManager;
|
||||
HardwareManagerImplementation *m_hardwareManager;
|
||||
DebugServerHandler *m_debugServerHandler;
|
||||
|
||||
NetworkManager *m_networkManager;
|
||||
UserManager *m_userManager;
|
||||
|
||||
@ -89,6 +89,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
basicConfiguration.insert("serverTime", JsonTypes::basicTypeToString(JsonTypes::Uint));
|
||||
basicConfiguration.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||
basicConfiguration.insert("language", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||
basicConfiguration.insert("debugServerEnabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
|
||||
returns.insert("basicConfiguration", basicConfiguration);
|
||||
QVariantList tcpServerConfigurations;
|
||||
tcpServerConfigurations.append(JsonTypes::serverConfigurationRef());
|
||||
@ -125,6 +126,13 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
returns.insert("configurationError", JsonTypes::configurationErrorRef());
|
||||
setReturns("SetLanguage", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("SetDebugServerEnabled", "Enable or disable the debug server.");
|
||||
params.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||
setParams("SetDebugServerEnabled", params);
|
||||
returns.insert("configurationError", JsonTypes::configurationErrorRef());
|
||||
setReturns("SetDebugServerEnabled", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("SetTcpServerConfiguration", "Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped.");
|
||||
params.insert("configuration", JsonTypes::serverConfigurationRef());
|
||||
@ -181,6 +189,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
params.insert("serverUuid", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||
params.insert("serverTime", JsonTypes::basicTypeToString(JsonTypes::Uint));
|
||||
params.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String));
|
||||
params.insert("debugServerEnabled", JsonTypes::basicTypeToString(JsonTypes::Bool));
|
||||
setParams("BasicConfigurationChanged", params);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
@ -214,6 +223,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent):
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::serverNameChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::timeZoneChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::localeChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::debugServerEnabledChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::tcpServerConfigurationChanged, this, &ConfigurationHandler::onTcpServerConfigurationChanged);
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::webServerConfigurationChanged, this, &ConfigurationHandler::onWebServerConfigurationChanged);
|
||||
connect(GuhCore::instance()->configuration(), &GuhConfiguration::webSocketServerConfigurationChanged, this, &ConfigurationHandler::onWebSocketServerConfigurationChanged);
|
||||
@ -416,6 +426,13 @@ JsonReply *ConfigurationHandler::SetCloudEnabled(const QVariantMap ¶ms) cons
|
||||
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
|
||||
}
|
||||
|
||||
JsonReply *ConfigurationHandler::SetDebugServerEnabled(const QVariantMap ¶ms) const
|
||||
{
|
||||
bool enabled = params.value("enabled").toBool();
|
||||
GuhCore::instance()->configuration()->setDebugServerEnabled(enabled);
|
||||
return createReply(statusToReply(GuhConfiguration::ConfigurationErrorNoError));
|
||||
}
|
||||
|
||||
void ConfigurationHandler::onBasicConfigurationChanged()
|
||||
{
|
||||
QVariantMap params;
|
||||
|
||||
@ -48,6 +48,7 @@ public:
|
||||
Q_INVOKABLE JsonReply *SetWebSocketServerConfiguration(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *DeleteWebSocketServerConfiguration(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *SetCloudEnabled(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *SetDebugServerEnabled(const QVariantMap ¶ms) const;
|
||||
|
||||
signals:
|
||||
void BasicConfigurationChanged(const QVariantMap ¶ms);
|
||||
|
||||
@ -1119,6 +1119,7 @@ QVariantMap JsonTypes::packBasicConfiguration()
|
||||
basicConfiguration.insert("serverTime", GuhCore::instance()->timeManager()->currentDateTime().toTime_t());
|
||||
basicConfiguration.insert("timeZone", QString::fromUtf8(GuhCore::instance()->timeManager()->timeZone()));
|
||||
basicConfiguration.insert("language", GuhCore::instance()->configuration()->locale().name());
|
||||
basicConfiguration.insert("debugServerEnabled", GuhCore::instance()->configuration()->debugServerEnabled());
|
||||
return basicConfiguration;
|
||||
}
|
||||
|
||||
|
||||
@ -96,6 +96,7 @@ HEADERS += guhcore.h \
|
||||
hardware/network/avahi/qtavahiservice_p.h \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation.h \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation_p.h \
|
||||
debugserverhandler.h
|
||||
|
||||
SOURCES += guhcore.cpp \
|
||||
tcpserver.cpp \
|
||||
@ -174,3 +175,4 @@ SOURCES += guhcore.cpp \
|
||||
hardware/network/avahi/qtavahiservice_p.cpp \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation.cpp \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation_p.cpp \
|
||||
debugserverhandler.cpp
|
||||
|
||||
@ -76,6 +76,7 @@
|
||||
#include "httpreply.h"
|
||||
#include "httprequest.h"
|
||||
#include "rest/restresource.h"
|
||||
#include "debugserverhandler.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QNetworkInterface>
|
||||
@ -281,14 +282,14 @@ void WebServer::readClient()
|
||||
QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
|
||||
QUuid clientId = m_clientList.key(socket);
|
||||
|
||||
// check client
|
||||
// Check client
|
||||
if (clientId.isNull()) {
|
||||
qCWarning(dcWebServer) << "Client not recognized";
|
||||
socket->close();
|
||||
return;
|
||||
}
|
||||
|
||||
// read HTTP request
|
||||
// Read HTTP request
|
||||
QByteArray data = socket->readAll();
|
||||
|
||||
HttpRequest request;
|
||||
@ -300,13 +301,13 @@ void WebServer::readClient()
|
||||
request = HttpRequest(data);
|
||||
}
|
||||
|
||||
// check if the request is complete
|
||||
// Check if the request is complete
|
||||
if (!request.isComplete()) {
|
||||
m_incompleteRequests.insert(socket, request);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the request is valid
|
||||
// Check if the request is valid
|
||||
if (!request.isValid()) {
|
||||
qCWarning(dcWebServer) << "Got invalid request:" << request.url().path();
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest);
|
||||
@ -316,7 +317,7 @@ void WebServer::readClient()
|
||||
return;
|
||||
}
|
||||
|
||||
// check HTTP version
|
||||
// Check HTTP version
|
||||
if (request.httpVersion() != "HTTP/1.1" && request.httpVersion() != "HTTP/1.0") {
|
||||
qCWarning(dcWebServer) << "HTTP version is not supported." << request.httpVersion();
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::HttpVersionNotSupported);
|
||||
@ -329,7 +330,7 @@ void WebServer::readClient()
|
||||
qCDebug(dcWebServer) << QString("Got valid request from %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||
qCDebug(dcWebServer) << request.methodString() << request.url().path();
|
||||
|
||||
// reset timout
|
||||
// Reset timout
|
||||
foreach (WebServerClient *webserverClient, m_webServerClients) {
|
||||
if (webserverClient->address() == socket->peerAddress()) {
|
||||
webserverClient->resetTimout(socket);
|
||||
@ -337,7 +338,7 @@ void WebServer::readClient()
|
||||
}
|
||||
}
|
||||
|
||||
// verify method
|
||||
// Verify method
|
||||
if (request.method() == HttpRequest::Unhandled) {
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::MethodNotAllowed);
|
||||
reply->setClientId(clientId);
|
||||
@ -347,13 +348,13 @@ void WebServer::readClient()
|
||||
return;
|
||||
}
|
||||
|
||||
// verify API query
|
||||
// Verify API query
|
||||
if (request.url().path().startsWith("/api/v1")) {
|
||||
emit httpRequestReady(clientId, request);
|
||||
return;
|
||||
}
|
||||
|
||||
// check icon call
|
||||
// Check icon call
|
||||
if (request.url().path().startsWith("/icons/") && request.method() == HttpRequest::Get) {
|
||||
HttpReply *reply = processIconRequest(request.url().path());
|
||||
reply->setClientId(clientId);
|
||||
@ -362,7 +363,37 @@ void WebServer::readClient()
|
||||
return;
|
||||
}
|
||||
|
||||
// check server.xml call
|
||||
// Check if this is a debug call
|
||||
if (request.url().path().startsWith("/debug")) {
|
||||
|
||||
// Check if debug server is enabled
|
||||
if (GuhCore::instance()->configuration()->debugServerEnabled()) {
|
||||
// Verify methods
|
||||
if (request.method() != HttpRequest::Get && request.method() != HttpRequest::Options) {
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::MethodNotAllowed);
|
||||
reply->setClientId(clientId);
|
||||
reply->setHeader(HttpReply::AllowHeader, "GET, OPTIONS");
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
HttpReply *reply = GuhCore::instance()->debugServerHandler()->processDebugRequest(request.url().path());
|
||||
reply->setClientId(clientId);
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
} else {
|
||||
qCWarning(dcWebServer()) << "The debug server handler is disabled. You can enable it by adding \'debugServerEnabled=true\' in the \'guhd\' section of the guhd.conf file.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setClientId(clientId);
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check server.xml call
|
||||
if (request.url().path() == "/server.xml" && request.method() == HttpRequest::Get) {
|
||||
qCDebug(dcWebServer) << "server XML request call";
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
@ -375,9 +406,9 @@ void WebServer::readClient()
|
||||
}
|
||||
|
||||
|
||||
// request for a file...
|
||||
// Request for a file...
|
||||
if (request.method() == HttpRequest::Get) {
|
||||
// check if the webinterface dir does exist, otherwise a filerequest is not relevant
|
||||
// Check if the webinterface dir does exist, otherwise a filerequest is not relevant
|
||||
if (!QDir(m_configuration.publicFolder).exists()) {
|
||||
qCWarning(dcWebServer) << "webinterface folder" << m_configuration.publicFolder << "does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
@ -396,7 +427,7 @@ void WebServer::readClient()
|
||||
qCDebug(dcWebServer) << "load file" << file.fileName();
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
|
||||
// check content type
|
||||
// Check content type
|
||||
if (file.fileName().endsWith(".html")) {
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/html; charset=\"utf-8\";");
|
||||
} else if (file.fileName().endsWith(".css")) {
|
||||
@ -429,7 +460,7 @@ void WebServer::readClient()
|
||||
}
|
||||
}
|
||||
|
||||
// reject everything else...
|
||||
// Reject everything else...
|
||||
qCWarning(dcWebServer) << "Unknown message received.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotImplemented);
|
||||
reply->setClientId(clientId);
|
||||
@ -441,7 +472,7 @@ void WebServer::onDisconnected()
|
||||
{
|
||||
QSslSocket* socket = static_cast<QSslSocket *>(sender());
|
||||
|
||||
// remove connection from server client
|
||||
// Remove connection from server client
|
||||
foreach (WebServerClient *client, m_webServerClients) {
|
||||
if (client->address() == socket->peerAddress()) {
|
||||
client->removeConnection(socket);
|
||||
@ -730,7 +761,6 @@ QByteArray WebServer::createServerXmlDocument(QHostAddress address)
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\class guhserver::WebServerClient
|
||||
\brief This class represents a client the web server for guhd.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2015-2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of guh. *
|
||||
* *
|
||||
@ -43,8 +43,8 @@
|
||||
|
||||
namespace guhserver {
|
||||
|
||||
class HttpRequest;
|
||||
class HttpReply;
|
||||
class HttpRequest;
|
||||
|
||||
class WebServerClient : public QObject
|
||||
{
|
||||
@ -98,6 +98,7 @@ private:
|
||||
|
||||
QByteArray createServerXmlDocument(QHostAddress address);
|
||||
HttpReply *processIconRequest(const QString &fileName);
|
||||
HttpReply *processDebugRequest(const QString &requestPath);
|
||||
|
||||
protected:
|
||||
void incomingConnection(qintptr socketDescriptor) override;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
1.1
|
||||
1.2
|
||||
{
|
||||
"methods": {
|
||||
"Actions.ExecuteAction": {
|
||||
@ -75,6 +75,7 @@
|
||||
},
|
||||
"returns": {
|
||||
"basicConfiguration": {
|
||||
"debugServerEnabled": "Bool",
|
||||
"language": "String",
|
||||
"serverName": "String",
|
||||
"serverTime": "Uint",
|
||||
@ -114,6 +115,15 @@
|
||||
"configurationError": "$ref:ConfigurationError"
|
||||
}
|
||||
},
|
||||
"Configuration.SetDebugServerEnabled": {
|
||||
"description": "Enable or disable the debug server.",
|
||||
"params": {
|
||||
"enabled": "String"
|
||||
},
|
||||
"returns": {
|
||||
"configurationError": "$ref:ConfigurationError"
|
||||
}
|
||||
},
|
||||
"Configuration.SetLanguage": {
|
||||
"description": "Sets the server language to the given language. See also: \"GetAvailableLanguages\"",
|
||||
"params": {
|
||||
@ -785,6 +795,7 @@
|
||||
"Configuration.BasicConfigurationChanged": {
|
||||
"description": "Emitted whenever the basic configuration of this server changes.",
|
||||
"params": {
|
||||
"debugServerEnabled": "Bool",
|
||||
"serverName": "String",
|
||||
"serverTime": "Uint",
|
||||
"serverUuid": "Uuid",
|
||||
|
||||
@ -45,6 +45,8 @@ private slots:
|
||||
void testServerName();
|
||||
void testLanguages();
|
||||
|
||||
void testDebugServerConfiguration();
|
||||
|
||||
private:
|
||||
QVariantMap loadBasicConfiguration();
|
||||
|
||||
@ -103,12 +105,16 @@ void TestConfigurations::testTimeZones()
|
||||
configurationChangedNotifications = checkNotifications(notificationSpy, "Configuration.BasicConfigurationChanged");
|
||||
QVERIFY2(configurationChangedNotifications.count() == 1, "Should get only one Configuration.BasicConfigurationChanged notification");
|
||||
QVariantMap notificationContent = configurationChangedNotifications.first().toMap().value("params").toMap();
|
||||
|
||||
qDebug() << notificationContent;
|
||||
|
||||
QVERIFY2(notificationContent.contains("basicConfiguration"), "Notification does not contain basicConfiguration");
|
||||
QVariantMap basicConfigurationNotificationMap = notificationContent.value("basicConfiguration").toMap();
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("language"), "Notification does not contain key language");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverName"), "Notification does not contain key serverName");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverTime"), "Notification does not contain key serverTime");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverUuid"), "Notification does not contain key serverUuid");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("debugServerEnabled"), "Notification does not contain key debugServerEnabled");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("timeZone"), "Notification does not contain key timeZone");
|
||||
QVERIFY2(basicConfigurationNotificationMap.value("timeZone").toString() == newTimeZone, "Notification does not contain the new timeZone");
|
||||
|
||||
@ -199,6 +205,7 @@ void TestConfigurations::testServerName()
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverTime"), "Notification does not contain key serverTime");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverUuid"), "Notification does not contain key serverUuid");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("timeZone"), "Notification does not contain key timeZone");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("debugServerEnabled"), "Notification does not contain key debugServerEnabled");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverName"), "Notification does not contain key serverName");
|
||||
QVERIFY2(basicConfigurationNotificationMap.value("serverName").toString() == newServerName, "Notification does not contain the new serverName");
|
||||
|
||||
@ -286,6 +293,117 @@ void TestConfigurations::testLanguages()
|
||||
disableNotifications();
|
||||
}
|
||||
|
||||
void TestConfigurations::testDebugServerConfiguration()
|
||||
{
|
||||
enableNotifications();
|
||||
|
||||
// Get current configurations
|
||||
QVariantMap basicConfigurationMap = loadBasicConfiguration();
|
||||
|
||||
bool debugServerEnabled = basicConfigurationMap.value("debugServerEnabled").toBool();
|
||||
qDebug() << "Debug server enabled" << debugServerEnabled;
|
||||
|
||||
QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
||||
|
||||
// Unchanged debug server
|
||||
QVariantMap params; QVariant response; QVariantList configurationChangedNotifications;
|
||||
params.insert("enabled", debugServerEnabled);
|
||||
response = injectAndWait("Configuration.SetDebugServerEnabled", params);
|
||||
verifyConfigurationError(response);
|
||||
|
||||
// Check notification not emitted
|
||||
notificationSpy.wait(500);
|
||||
configurationChangedNotifications = checkNotifications(notificationSpy, "Configuration.BasicConfigurationChanged");
|
||||
QVERIFY2(configurationChangedNotifications.count() == 0, "Got Configuration.BasicConfigurationChanged notification but should have not.");
|
||||
|
||||
// Enable debug server
|
||||
bool newValue = true;
|
||||
params.clear(); response.clear(); configurationChangedNotifications.clear();
|
||||
params.insert("enabled", newValue);
|
||||
|
||||
notificationSpy.clear();
|
||||
response = injectAndWait("Configuration.SetDebugServerEnabled", params);
|
||||
verifyConfigurationError(response);
|
||||
|
||||
// Check notification not emitted
|
||||
notificationSpy.wait(500);
|
||||
configurationChangedNotifications = checkNotifications(notificationSpy, "Configuration.BasicConfigurationChanged");
|
||||
QVariantMap notificationContent = configurationChangedNotifications.first().toMap().value("params").toMap();
|
||||
QVERIFY2(notificationContent.contains("basicConfiguration"), "Notification does not contain basicConfiguration");
|
||||
QVERIFY2(configurationChangedNotifications.count() == 1, "Should get only one Configuration.BasicConfigurationChanged notification");
|
||||
QVariantMap basicConfigurationNotificationMap = notificationContent.value("basicConfiguration").toMap();
|
||||
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("language"), "Notification does not contain key language");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverTime"), "Notification does not contain key serverTime");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverUuid"), "Notification does not contain key serverUuid");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("timeZone"), "Notification does not contain key timeZone");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("serverName"), "Notification does not contain key serverName");
|
||||
QVERIFY2(basicConfigurationNotificationMap.contains("debugServerEnabled"), "Notification does not contain key debugServerEnabled");
|
||||
QVERIFY2(basicConfigurationNotificationMap.value("debugServerEnabled").toBool() == newValue, "Notification does not contain the new debugServerEnabled");
|
||||
|
||||
qDebug() << "TestWebserver starting";
|
||||
foreach (const WebServerConfiguration &config, GuhCore::instance()->configuration()->webServerConfigurations()) {
|
||||
if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) {
|
||||
qDebug() << "Already have a webserver listening on 127.0.0.1:3333";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Creating new webserver instance on 127.0.0.1:3333";
|
||||
WebServerConfiguration config;
|
||||
config.id = "Testwebserver for debug server interface";
|
||||
config.address = QHostAddress("127.0.0.1");
|
||||
config.port = 3333;
|
||||
config.sslEnabled = true;
|
||||
GuhCore::instance()->configuration()->setWebServerConfiguration(config);
|
||||
|
||||
// Webserver request
|
||||
QNetworkAccessManager nam;
|
||||
connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply* reply, const QList<QSslError> &) {
|
||||
reply->ignoreSslErrors();
|
||||
});
|
||||
QSignalSpy namSpy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
// Check if debug interface is reachable
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl("https://localhost:3333/debug/"));
|
||||
QNetworkReply *reply = nam.get(request);
|
||||
|
||||
namSpy.wait();
|
||||
QVERIFY2(namSpy.count() > 0, "expected response from webserver");
|
||||
|
||||
qDebug() << reply->readAll();
|
||||
|
||||
bool ok = false;
|
||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok);
|
||||
QVERIFY2(ok, "Could not convert statuscode from response to int");
|
||||
QCOMPARE(statusCode, 200);
|
||||
reply->deleteLater();
|
||||
|
||||
// Disable debug server
|
||||
params.clear(); response.clear();
|
||||
params.insert("enabled", false);
|
||||
response = injectAndWait("Configuration.SetDebugServerEnabled", params);
|
||||
verifyConfigurationError(response);
|
||||
|
||||
// Check if debug interface is not reachable any more
|
||||
namSpy.clear();
|
||||
reply = nam.get(request);
|
||||
|
||||
namSpy.wait();
|
||||
QVERIFY2(namSpy.count() > 0, "expected response from webserver");
|
||||
|
||||
ok = false;
|
||||
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok);
|
||||
QVERIFY2(ok, "Could not convert statuscode from response to int");
|
||||
QCOMPARE(statusCode, 404);
|
||||
reply->deleteLater();
|
||||
|
||||
GuhCore::instance()->configuration()->removeWebServerConfiguration(config.id);
|
||||
|
||||
disableNotifications();
|
||||
}
|
||||
|
||||
QVariantMap TestConfigurations::loadBasicConfiguration()
|
||||
{
|
||||
QVariant response = injectAndWait("Configuration.GetConfigurations");
|
||||
|
||||
@ -68,6 +68,9 @@ private slots:
|
||||
void getIcons_data();
|
||||
void getIcons();
|
||||
|
||||
void getDebugServer_data();
|
||||
void getDebugServer();
|
||||
|
||||
public slots:
|
||||
void onSslErrors(const QList<QSslError> &) {
|
||||
qWarning() << "SSL error";
|
||||
@ -472,5 +475,160 @@ void TestWebserver::getIcons()
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void TestWebserver::getDebugServer_data()
|
||||
{
|
||||
QTest::addColumn<QString>("method");
|
||||
QTest::addColumn<QString>("query");
|
||||
QTest::addColumn<bool>("serverEnabled");
|
||||
QTest::addColumn<int>("expectedStatusCode");
|
||||
|
||||
// debug enabled
|
||||
QTest::newRow("GET /debug | server enabled | 200") << "get" << "/debug" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug | server enabled | 200") << "options" << "/debug" << true << 200;
|
||||
QTest::newRow("PUT /debug | server enabled | 405") << "put" << "/debug" << true << 405;
|
||||
QTest::newRow("POST /debug | server enabled | 405") << "post" << "/debug" << true << 405;
|
||||
QTest::newRow("DELETE /debug | server enabled | 405") << "delete" << "/debug" << true << 405;
|
||||
|
||||
// debug disabled
|
||||
QTest::newRow("GET /debug | server disabled | 404") << "get" << "/debug" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug | server disabled | 404") << "options" << "/debug" << false << 404;
|
||||
QTest::newRow("PUT /debug | server disabled | 404") << "put" << "/debug" << false << 404;
|
||||
QTest::newRow("POST /debug | server disabled | 404") << "post" << "/debug" << false << 404;
|
||||
QTest::newRow("DELETE /debug | server disabled | 404") << "delete" << "/debug" << false << 404;
|
||||
|
||||
// logdb enabled
|
||||
QTest::newRow("GET /debug/logdb | server enabled | 200") << "get" << "/debug/logdb" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug/logdb | server enabled | 200") << "options" << "/debug/logdb" << true << 200;
|
||||
QTest::newRow("PUT /debug/logdb | server enabled | 405") << "put" << "/debug/logdb" << true << 405;
|
||||
QTest::newRow("POST /debug/logdb | server enabled | 405") << "post" << "/debug/logdb" << true << 405;
|
||||
QTest::newRow("DELETE /debug/logdb | server enabled | 405") << "delete" << "/debug/logdb" << true << 405;
|
||||
|
||||
// logdb disabled
|
||||
QTest::newRow("GET /debug/logdb | server enabled | 404") << "get" << "/debug/logdb" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug/logdb | server enabled | 404") << "options" << "/debug/logdb" << false << 404;
|
||||
QTest::newRow("PUT /debug/logdb | server enabled | 404") << "put" << "/debug/logdb" << false << 404;
|
||||
QTest::newRow("POST /debug/logdb | server enabled | 404") << "post" << "/debug/logdb" << false << 404;
|
||||
QTest::newRow("DELETE /debug/logdb | server enabled | 404") << "delete" << "/debug/logdb" << false << 404;
|
||||
|
||||
// syslog enabled
|
||||
QTest::newRow("GET /debug/syslog | server enabled | 200") << "get" << "/debug/syslog" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug/syslog | server enabled | 200") << "options" << "/debug/logdb" << true << 200;
|
||||
QTest::newRow("PUT /debug/syslog | server enabled | 405") << "put" << "/debug/logdb" << true << 405;
|
||||
QTest::newRow("POST /debug/syslog | server enabled | 405") << "post" << "/debug/logdb" << true << 405;
|
||||
QTest::newRow("DELETE /debug/syslog | server enabled | 405") << "delete" << "/debug/logdb" << true << 405;
|
||||
|
||||
// syslog disabled
|
||||
QTest::newRow("GET /debug/syslog | server enabled | 404") << "get" << "/debug/syslog" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug/syslog | server enabled | 404") << "options" << "/debug/syslog" << false << 404;
|
||||
QTest::newRow("PUT /debug/syslog | server enabled | 404") << "put" << "/debug/syslog" << false << 404;
|
||||
QTest::newRow("POST /debug/syslog | server enabled | 404") << "post" << "/debug/syslog" << false << 404;
|
||||
QTest::newRow("DELETE /debug/syslog | server enabled | 404") << "delete" << "/debug/syslog" << false << 404;
|
||||
|
||||
// settings/guhd enabled
|
||||
QTest::newRow("GET /debug/settings/guhd | server enabled | 200") << "get" << "/debug/settings/guhd" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug/settings/guhd | server enabled | 200") << "options" << "/debug/settings/guhd" << true << 200;
|
||||
QTest::newRow("PUT /debug/settings/guhd | server enabled | 405") << "put" << "/debug/settings/guhd" << true << 405;
|
||||
QTest::newRow("POST /debug/settings/guhd | server enabled | 405") << "post" << "/debug/settings/guhd" << true << 405;
|
||||
QTest::newRow("DELETE /debug/settings/guhd | server enabled | 405") << "delete" << "/debug/settings/guhd" << true << 405;
|
||||
|
||||
// settings/guhd disabled
|
||||
QTest::newRow("GET /debug/settings/guhd | server enabled | 404") << "get" << "/debug/settings/guhd" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug/settings/guhd | server enabled | 404") << "options" << "/debug/settings/guhd" << false << 404;
|
||||
QTest::newRow("PUT /debug/settings/guhd | server enabled | 404") << "put" << "/debug/settings/guhd" << false << 404;
|
||||
QTest::newRow("POST /debug/settings/guhd | server enabled | 404") << "post" << "/debug/settings/guhd" << false << 404;
|
||||
QTest::newRow("DELETE /debug/settings/guhd | server enabled | 404") << "delete" << "/debug/settings/guhd" << false << 404;
|
||||
|
||||
// settings/devices enabled
|
||||
QTest::newRow("GET /debug/settings/devices | server enabled | 200") << "get" << "/debug/settings/devices" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug/settings/devices | server enabled | 200") << "options" << "/debug/settings/devices" << true << 200;
|
||||
QTest::newRow("PUT /debug/settings/devices | server enabled | 405") << "put" << "/debug/settings/devices" << true << 405;
|
||||
QTest::newRow("POST /debug/settings/devices | server enabled | 405") << "post" << "/debug/settings/devices" << true << 405;
|
||||
QTest::newRow("DELETE /debug/settings/devices | server enabled | 405") << "delete" << "/debug/settings/devices" << true << 405;
|
||||
|
||||
// settings/devices disabled
|
||||
QTest::newRow("GET /debug/settings/devices | server enabled | 404") << "get" << "/debug/settings/devices" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug/settings/devices | server enabled | 404") << "options" << "/debug/settings/devices" << false << 404;
|
||||
QTest::newRow("PUT /debug/settings/devices | server enabled | 404") << "put" << "/debug/settings/devices" << false << 404;
|
||||
QTest::newRow("POST /debug/settings/devices | server enabled | 404") << "post" << "/debug/settings/devices" << false << 404;
|
||||
QTest::newRow("DELETE /debug/settings/devices | server enabled | 404") << "delete" << "/debug/settings/devices" << false << 404;
|
||||
|
||||
// settings/rules enabled
|
||||
QTest::newRow("GET /debug/settings/rules | server enabled | 200") << "get" << "/debug/settings/rules" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug/settings/rules | server enabled | 200") << "options" << "/debug/settings/rules" << true << 200;
|
||||
QTest::newRow("PUT /debug/settings/rules | server enabled | 405") << "put" << "/debug/settings/rules" << true << 405;
|
||||
QTest::newRow("POST /debug/settings/rules | server enabled | 405") << "post" << "/debug/settings/rules" << true << 405;
|
||||
QTest::newRow("DELETE /debug/settings/rules | server enabled | 405") << "delete" << "/debug/settings/rules" << true << 405;
|
||||
|
||||
// settings/rules disabled
|
||||
QTest::newRow("GET /debug/settings/rules | server enabled | 404") << "get" << "/debug/settings/rules" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug/settings/rules | server enabled | 404") << "options" << "/debug/settings/rules" << false << 404;
|
||||
QTest::newRow("PUT /debug/settings/rules | server enabled | 404") << "put" << "/debug/settings/rules" << false << 404;
|
||||
QTest::newRow("POST /debug/settings/rules | server enabled | 404") << "post" << "/debug/settings/rules" << false << 404;
|
||||
QTest::newRow("DELETE /debug/settings/rules | server enabled | 404") << "delete" << "/debug/settings/rules" << false << 404;
|
||||
|
||||
// settings/devicestates enabled
|
||||
QTest::newRow("GET /debug/settings/devicestates | server enabled | 200") << "get" << "/debug/settings/devicestates" << true << 200;
|
||||
QTest::newRow("OPTIONS /debug/settings/devicestates | server enabled | 200") << "options" << "/debug/settings/devicestates" << true << 200;
|
||||
QTest::newRow("PUT /debug/settings/devicestates | server enabled | 405") << "put" << "/debug/settings/devicestates" << true << 405;
|
||||
QTest::newRow("POST /debug/settings/devicestates | server enabled | 405") << "post" << "/debug/settings/devicestates" << true << 405;
|
||||
QTest::newRow("DELETE /debug/settings/devicestates | server enabled | 405") << "delete" << "/debug/settings/devicestates" << true << 405;
|
||||
|
||||
// settings/devicestates disabled
|
||||
QTest::newRow("GET /debug/settings/devicestates | server enabled | 404") << "get" << "/debug/settings/devicestates" << false << 404;
|
||||
QTest::newRow("OPTIONS /debug/settings/devicestates | server enabled | 404") << "options" << "/debug/settings/devicestates" << false << 404;
|
||||
QTest::newRow("PUT /debug/settings/devicestates | server enabled | 404") << "put" << "/debug/settings/devicestates" << false << 404;
|
||||
QTest::newRow("POST /debug/settings/devicestates | server enabled | 404") << "post" << "/debug/settings/devicestates" << false << 404;
|
||||
QTest::newRow("DELETE /debug/settings/devicestates | server enabled | 404") << "delete" << "/debug/settings/devicestates" << false << 404;
|
||||
}
|
||||
|
||||
void TestWebserver::getDebugServer()
|
||||
{
|
||||
QFETCH(QString, method);
|
||||
QFETCH(QString, query);
|
||||
QFETCH(bool, serverEnabled);
|
||||
QFETCH(int, expectedStatusCode);
|
||||
|
||||
// Enable/disable debug server
|
||||
QVariantMap params; QVariant response;
|
||||
params.insert("enabled", serverEnabled);
|
||||
response = injectAndWait("Configuration.SetDebugServerEnabled", params);
|
||||
verifyConfigurationError(response);
|
||||
|
||||
QNetworkAccessManager nam;
|
||||
bool ok = false;
|
||||
int statusCode = 0;
|
||||
|
||||
QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||
connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply* reply, const QList<QSslError> &) {
|
||||
reply->ignoreSslErrors();
|
||||
});
|
||||
|
||||
QNetworkReply *reply = nullptr;
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl("https://localhost:3333" + query));
|
||||
|
||||
clientSpy.clear();
|
||||
|
||||
if (method == "get") {
|
||||
reply = nam.get(request);
|
||||
} else if (method == "options") {
|
||||
reply = nam.sendCustomRequest(request, "OPTIONS");
|
||||
} else if (method == "post") {
|
||||
reply = nam.post(request, "");
|
||||
} else if (method == "delete") {
|
||||
reply = nam.deleteResource(request);
|
||||
} else if (method == "put") {
|
||||
reply = nam.put(request, "");
|
||||
}
|
||||
|
||||
clientSpy.wait();
|
||||
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||
|
||||
ok = false;
|
||||
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok);
|
||||
QVERIFY2(ok, "Could not convert statuscode from response to int");
|
||||
QCOMPARE(statusCode, expectedStatusCode);
|
||||
}
|
||||
|
||||
#include "testwebserver.moc"
|
||||
QTEST_MAIN(TestWebserver)
|
||||
|
||||
Reference in New Issue
Block a user