Files
WifiLamp/relaiswebserver.cpp
T

170 lines
6.3 KiB
C++

#include "relaiswebserver.h"
#include <QStringBuilder>
#include "httpclientconnection.h"
#include "httpcontainers.h"
#include "relaisserver.h"
#include "relaisclient.h"
RelaisWebserver::RelaisWebserver(RelaisServer *relaisServer, QObject *parent) :
HttpServer(parent),
m_relaisServer(relaisServer)
{
}
void RelaisWebserver::handleRequest(HttpClientConnection *connection, const HttpRequest &request)
{
qDebug() << request.path;
if(!request.path.startsWith('/'))
{
HttpResponse response;
response.protocol = request.protocol;
response.statusCode = HttpResponse::StatusCode::BadRequest;
response.headers.insert(QStringLiteral("Server"), QStringLiteral("Hatschi Server 1.0"));
response.headers.insert(QStringLiteral("Content-Type"), QStringLiteral("text/html"));
connection->sendResponse(response, tr("Path does not start with /"));
return;
}
if(request.path == QStringLiteral("/"))
{
handleRoot(connection, request);
}
else if(request.path == QStringLiteral("/refresh"))
{
for(auto client : m_relaisServer->clients())
client->requestStatus();
redirectRoot(connection, request);
}
else if(request.path.startsWith("/devices/"))
{
auto parts = request.path.split('/');
if(parts.count() != 4)
{
handle404(connection, request);
return;
}
RelaisClient *client;
{
auto iter = std::find_if(m_relaisServer->clients().constBegin(), m_relaisServer->clients().constEnd(),
[&parts](const RelaisClient *client){
return clientId(client) == parts.at(2);
});
if(iter == m_relaisServer->clients().constEnd())
{
handle404(connection, request);
return;
}
client = *iter;
}
static const QHash<QString, std::function<void(RelaisClient*)> > actions {
{ QStringLiteral("toggle"), [](RelaisClient *client){ client->toggle(); } },
{ QStringLiteral("on"), [](RelaisClient *client){ client->on(); } },
{ QStringLiteral("off"), [](RelaisClient *client){ client->off(); } },
{ QStringLiteral("refresh"), [](RelaisClient *client){ client->requestStatus(); } },
{ QStringLiteral("reboot"), [](RelaisClient *client){ client->reboot(); } },
{ QStringLiteral("delete"), [](RelaisClient *client){ client->deleteLater(); } }
};
{
auto iter = actions.find(parts.at(3));
if(iter == actions.constEnd())
handle404(connection, request);
else
{
(*iter)(client);
redirectRoot(connection, request);
}
}
}
else
{
handle404(connection, request);
}
}
void RelaisWebserver::handleRoot(HttpClientConnection *connection, const HttpRequest &request)
{
QString output = "<h1>Lampen-Steuerung</h1>";
output.append("<a href=\"/refresh\">Alle aktualisieren</a>");
output.append("<table border=\"1\">");
output.append("<thead>");
output.append("<tr>");
output.append("<th>IP-Adress</th>");
output.append("<th>Name</th>");
output.append("<th>Status</th>");
output.append("<th>Actions</th>");
output.append("</tr>");
output.append("</thead>");
output.append("<tbody>");
for(auto client : m_relaisServer->clients())
{
output.append("<tr>");
output.append("<td>" % clientId(client, true).toHtmlEscaped() % "</td>");
output.append("<td>" % client->name().toHtmlEscaped() % "</td>");
output.append("<td>" % client->status().toHtmlEscaped() % "</td>");
output.append("<td>");
output.append("<a href=\"/devices/" % clientId(client).toHtmlEscaped() % "/toggle\">" % tr("Toggle") % "</a> ");
output.append("<a href=\"/devices/" % clientId(client).toHtmlEscaped() % "/on\">" % tr("On") % "</a> ");
output.append("<a href=\"/devices/" % clientId(client).toHtmlEscaped() % "/off\">" % tr("Off") % "</a> ");
output.append("<a href=\"/devices/" % clientId(client).toHtmlEscaped() % "/refresh\">" % tr("Refresh") % "</a> ");
output.append("<a href=\"/devices/" % clientId(client).toHtmlEscaped() % "/reboot\">" % tr("Reboot") % "</a> ");
output.append("<a href=\"/devices/" % clientId(client).toHtmlEscaped() % "/delete\">" % tr("Delete") % "</a> ");
output.append("</td>");
output.append("</tr>");
}
output.append("</tbody>");
output.append("</table>");
HttpResponse response;
response.protocol = request.protocol;
response.statusCode = HttpResponse::StatusCode::OK;
response.headers.insert(QStringLiteral("Server"), QStringLiteral("Hatschi Server 1.0"));
response.headers.insert(QStringLiteral("Content-Type"), QStringLiteral("text/html"));
connection->sendResponse(response, output);
}
void RelaisWebserver::redirectRoot(HttpClientConnection *connection, const HttpRequest &request)
{
HttpResponse response;
response.protocol = request.protocol;
response.statusCode = HttpResponse::StatusCode::Found;
response.headers.insert(QStringLiteral("Server"), QStringLiteral("Hatschi Server 1.0"));
response.headers.insert(QStringLiteral("Content-Type"), QStringLiteral("text/html"));
response.headers.insert(QStringLiteral("Location"), QStringLiteral("/"));
connection->sendResponse(response, "<a href=\"/\">" % tr("Follow this link") % "</a>");
}
void RelaisWebserver::handle404(HttpClientConnection *connection, const HttpRequest &request)
{
HttpResponse response;
response.protocol = request.protocol;
response.statusCode = HttpResponse::StatusCode::NotFound;
response.headers.insert(QStringLiteral("Server"), QStringLiteral("Hatschi Server 1.0"));
response.headers.insert(QStringLiteral("Content-Type"), QStringLiteral("text/html"));
connection->sendResponse(response, tr("Not Found"));
}
QString RelaisWebserver::clientId(const RelaisClient *client, bool forceIp)
{
if(!client->name().isEmpty() && !forceIp)
return client->name();
return client->peerAddress().toString() % ':' % QString::number(client->peerPort());
}