Add network test functionality and add live log viewer for debug server interface
@ -1,8 +1,15 @@
|
||||
<RCC>
|
||||
<qresource prefix="">
|
||||
<qresource prefix="/">
|
||||
<file>logo.svg</file>
|
||||
<file>warning.svg</file>
|
||||
<file>script.js</file>
|
||||
<file>styles.css</file>
|
||||
<file>favicons/favicon-16x16.png</file>
|
||||
<file>favicons/favicon-32x32.png</file>
|
||||
<file>favicons/favicon-96x96.png</file>
|
||||
<file>favicons/favicon-128.png</file>
|
||||
<file>favicons/favicon-196x196.png</file>
|
||||
<file>favicons/favicon.ico</file>
|
||||
<file>favicons/favicon.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
|
||||
BIN
data/debug-interface/favicons/apple-touch-icon-114x114.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-120x120.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-152x152.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-57x57.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-60x60.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
data/debug-interface/favicons/apple-touch-icon-76x76.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
data/debug-interface/favicons/favicon-128.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
data/debug-interface/favicons/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 305 B |
BIN
data/debug-interface/favicons/favicon-196x196.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
data/debug-interface/favicons/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 615 B |
BIN
data/debug-interface/favicons/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
data/debug-interface/favicons/favicon.ico
Normal file
|
After Width: | Height: | Size: 34 KiB |
57
data/debug-interface/favicons/favicon.svg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
data/debug-interface/favicons/mstile-144x144.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
data/debug-interface/favicons/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
data/debug-interface/favicons/mstile-310x150.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
data/debug-interface/favicons/mstile-310x310.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
data/debug-interface/favicons/mstile-70x70.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
152
data/debug-interface/script.js
Normal file
@ -0,0 +1,152 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* nymea 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. *
|
||||
* *
|
||||
* nymea 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 nymea. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
/* ========================================================================*/
|
||||
/* Websocket connection
|
||||
/* ========================================================================*/
|
||||
|
||||
var webSocket = null;
|
||||
|
||||
function connectWebsocket() {
|
||||
var urlString = "ws://" + window.location.hostname + ":2626"
|
||||
console.log("Connecting to: " + urlString);
|
||||
|
||||
try {
|
||||
webSocket = new WebSocket(urlString);
|
||||
|
||||
webSocket.onopen = function(openEvent) {
|
||||
console.log("WebSocket connected: " + JSON.stringify(openEvent, null, 4));
|
||||
document.getElementById("connectWebsocketButton").disabled = true;
|
||||
document.getElementById("disconnectWebsocketButton").disabled = false;
|
||||
};
|
||||
|
||||
webSocket.onclose = function (closeEvent) {
|
||||
console.log("WebSocket disconnected: " + JSON.stringify(closeEvent, null, 4));
|
||||
document.getElementById("connectWebsocketButton").disabled = false;
|
||||
document.getElementById("disconnectWebsocketButton").disabled = true;
|
||||
};
|
||||
|
||||
webSocket.onerror = function (errorEvent) {
|
||||
console.log("WebSocket error: " + JSON.stringify(errorEvent, null, 4));
|
||||
};
|
||||
|
||||
webSocket.onmessage = function (messageEvent) {
|
||||
var message = messageEvent.data;
|
||||
console.log("WebSocket data received: " + message);
|
||||
document.getElementById("logsTextArea").value += message;
|
||||
};
|
||||
|
||||
} catch (exception) {
|
||||
console.error(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function disconnectWebsocket() {
|
||||
console.log("Disconnecting from: " + webSocket.url);
|
||||
webSocket.close()
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ========================================================================*/
|
||||
/* File download function
|
||||
/* ========================================================================*/
|
||||
|
||||
function downloadFile(filePath, fileName) {
|
||||
console.log("Download file requested " + filePath + " --> " + fileName);
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute('href', filePath);
|
||||
element.setAttribute('download', fileName);
|
||||
element.style.display = 'none';
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
/* ========================================================================*/
|
||||
/* Network test functions
|
||||
/* ========================================================================*/
|
||||
|
||||
function startPingTest() {
|
||||
console.log("Start ping test");
|
||||
var textArea = document.getElementById("pingTextArea");
|
||||
var button = document.getElementById("pingButton");
|
||||
// Clear the text output
|
||||
textArea.value = "";
|
||||
|
||||
// Request ping output
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", "/debug/ping", true);
|
||||
request.send(null);
|
||||
button.disabled = true
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState == 4) {
|
||||
console.log(request.responseText);
|
||||
textArea.value = request.responseText
|
||||
button.disabled = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function startDigTest() {
|
||||
console.log("Start dig test");
|
||||
var textArea = document.getElementById("digTextArea");
|
||||
var button = document.getElementById("digButton");
|
||||
|
||||
// Clear the text output
|
||||
textArea.value = "";
|
||||
|
||||
// Request dig output
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", "/debug/dig", true);
|
||||
request.send(null);
|
||||
button.disabled = true
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState == 4) {
|
||||
console.log(request.responseText);
|
||||
textArea.value = request.responseText
|
||||
button.disabled = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function startTracePathTest() {
|
||||
console.log("Start trace path test");
|
||||
var textArea = document.getElementById("tracePathTextArea");
|
||||
var button = document.getElementById("tracePathButton");
|
||||
|
||||
// Clear the text output
|
||||
textArea.value = "";
|
||||
|
||||
// Request dig output
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", "/debug/tracepath", true);
|
||||
request.send(null);
|
||||
button.disabled = true
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState == 4) {
|
||||
console.log(request.responseText);
|
||||
textArea.value = request.responseText
|
||||
button.disabled = false
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -20,120 +20,144 @@
|
||||
|
||||
html,
|
||||
body {
|
||||
margin:0;
|
||||
padding:0;
|
||||
height:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #676767;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
text-align: center;
|
||||
color: #676767;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
color: #676767;
|
||||
text-transform: none;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
color: #676767;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 3px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: #676767;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
text-align: left;
|
||||
padding: 3px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: #676767;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
hr {
|
||||
color: #efefef;
|
||||
color: #efefef;
|
||||
}
|
||||
|
||||
table {
|
||||
display: table;
|
||||
border-collapse: colapse;
|
||||
border-color: #efefef;
|
||||
width: 100%;
|
||||
display: table;
|
||||
border-collapse: colapse;
|
||||
border-color: #efefef;
|
||||
min-height: 100px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: #3a4055;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
min-height: 100px;
|
||||
text-align: left;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.console-textarea {
|
||||
color: white;
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
font-family: "Ubuntu Mono";
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.nymea-main-logo {
|
||||
left: 0;
|
||||
height: 85px;
|
||||
min-height: 85px;
|
||||
max-height: 85px;
|
||||
vertical-align: middle;
|
||||
left: 0;
|
||||
height: 85px;
|
||||
min-height: 85px;
|
||||
max-height: 85px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: #ed3146;
|
||||
border-radius: 20px;
|
||||
opacity: 0.8;
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #ed3146;
|
||||
border-radius: 10px;
|
||||
opacity: 0.8;
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.warning-message {
|
||||
padding:30px;
|
||||
margin-left: 60px;
|
||||
opacity: 1;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
text-align: center;
|
||||
float: none;
|
||||
padding: 30px;
|
||||
margin-left: 60px;
|
||||
opacity: 1;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
font-family: "Ubuntu", Helvetica, "Helvetica Neue", Arial, sans-serif;
|
||||
text-align: center;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.warning-image {
|
||||
padding:12px;
|
||||
height: 60px;
|
||||
min-height: 60px;
|
||||
max-height: 60px;
|
||||
float: left;
|
||||
padding:12px;
|
||||
height: 60px;
|
||||
min-height: 60px;
|
||||
max-height: 60px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.warning:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.download-row {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.download-name-column {
|
||||
float: left;
|
||||
width: 30%;
|
||||
padding: 10px;
|
||||
float: left;
|
||||
width: 20%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.download-path-column {
|
||||
float: left;
|
||||
width: 40%;
|
||||
padding: 10px;
|
||||
float: left;
|
||||
width: 40%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.download-button-column {
|
||||
float: left;
|
||||
width: 20%;
|
||||
padding: 10px;
|
||||
float: left;
|
||||
width: 20%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.show-button-column {
|
||||
float: left;
|
||||
width: 10%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.download-row: after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.button {
|
||||
@ -146,34 +170,45 @@ button {
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
border-radius: 10px;
|
||||
opacity: 0.8;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.button:disabled,
|
||||
.button[disabled]{
|
||||
background-color: #cccccc;
|
||||
color: #676767;
|
||||
}
|
||||
|
||||
.container {
|
||||
min-height:100%;
|
||||
position:relative;
|
||||
min-height:100%;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding:10px;
|
||||
background-color: #efefef;
|
||||
text-align: center;
|
||||
padding:10px;
|
||||
background-color: #efefef;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.body {
|
||||
padding-left: 15%;
|
||||
padding-right: 15%;
|
||||
padding-bottom:120px;
|
||||
padding-left: 15%;
|
||||
padding-right: 15%;
|
||||
padding-bottom:120px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
left:0;
|
||||
right:0;
|
||||
width:100%;
|
||||
height:100px;
|
||||
background-color: #efefef;
|
||||
color: #676767;
|
||||
text-align: center;
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
left:0;
|
||||
right:0;
|
||||
width:100%;
|
||||
height:100px;
|
||||
background-color: #efefef;
|
||||
color: #676767;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -21,7 +21,10 @@
|
||||
#ifndef DEBUGSERVERHANDLER_H
|
||||
#define DEBUGSERVERHANDLER_H
|
||||
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QWebSocketServer>
|
||||
|
||||
#include "httpreply.h"
|
||||
|
||||
@ -35,15 +38,41 @@ public:
|
||||
|
||||
HttpReply *processDebugRequest(const QString &requestPath);
|
||||
|
||||
static QList<QWebSocket *> s_websocketClients;
|
||||
static void consoleLogHandler(QtMsgType type, const QMessageLogContext& context, const QString& message);
|
||||
|
||||
private:
|
||||
QByteArray createDebugXmlDocument();
|
||||
QByteArray createErrorXmlDocument(HttpReply::HttpStatusCode statusCode, const QString &errorMessage);
|
||||
QByteArray loadResourceFile(const QString &resourceFileName);
|
||||
QTimer *m_timer = nullptr;
|
||||
QWebSocketServer *m_websocketServer = nullptr;
|
||||
|
||||
QProcess *m_pingProcess = nullptr;
|
||||
HttpReply *m_pingReply = nullptr;
|
||||
|
||||
QProcess *m_digProcess = nullptr;
|
||||
HttpReply *m_digReply = nullptr;
|
||||
|
||||
QProcess *m_tracePathProcess = nullptr;
|
||||
HttpReply *m_tracePathReply = nullptr;
|
||||
|
||||
QByteArray loadResourceData(const QString &resourceFileName);
|
||||
QString getResourceFileName(const QString &requestPath);
|
||||
bool resourceFileExits(const QString &requestPath);
|
||||
|
||||
HttpReply *processDebugFileRequest(const QString &requestPath);
|
||||
|
||||
QByteArray createDebugXmlDocument();
|
||||
QByteArray createErrorXmlDocument(HttpReply::HttpStatusCode statusCode, const QString &errorMessage);
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
void onWebsocketClientConnected();
|
||||
void onWebsocketClientDisconnected();
|
||||
void onWebsocketClientError(QAbstractSocket::SocketError error);
|
||||
|
||||
void onPingProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onDigProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onTracePathProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -417,7 +417,7 @@ QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType)
|
||||
*/
|
||||
void HttpReply::startWait()
|
||||
{
|
||||
m_timer->start(10000);
|
||||
m_timer->start(60000);
|
||||
}
|
||||
|
||||
void HttpReply::timeout()
|
||||
|
||||
@ -132,7 +132,7 @@ QUrl WebServer::serverUrl() const
|
||||
void WebServer::sendHttpReply(HttpReply *reply)
|
||||
{
|
||||
// get the right socket
|
||||
QSslSocket *socket = 0;
|
||||
QSslSocket *socket = nullptr;
|
||||
socket = m_clientList.value(reply->clientId());
|
||||
if (!socket) {
|
||||
qCWarning(dcWebServer) << "Invalid socket pointer! This should never happen!!! Missing clientId in reply?";
|
||||
@ -141,7 +141,7 @@ void WebServer::sendHttpReply(HttpReply *reply)
|
||||
|
||||
// send raw data
|
||||
reply->packReply();
|
||||
qCDebug(dcWebServer) << "respond" << reply->httpStatusCode() << reply->httpReasonPhrase();
|
||||
qCDebug(dcWebServer) << "Respond" << reply->httpStatusCode() << reply->httpReasonPhrase();
|
||||
socket->write(reply->data());
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
||||
|
||||
// make sure the file is in the public directory
|
||||
if (!file.canonicalFilePath().startsWith(QDir(m_configuration.publicFolder).canonicalPath())) {
|
||||
qCWarning(dcWebServer) << "requested file" << file.fileName() << "is outside the public folder.";
|
||||
qCWarning(dcWebServer) << "Requested file" << file.fileName() << "is outside the public folder.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setClientId(m_clientList.key(socket));
|
||||
sendHttpReply(reply);
|
||||
@ -171,7 +171,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
||||
|
||||
// make sure we can read the file
|
||||
if (!file.isReadable()) {
|
||||
qCWarning(dcWebServer) << "requested file" << file.fileName() << "is not readable.";
|
||||
qCWarning(dcWebServer) << "Requested file" << file.fileName() << "is not readable.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||
reply->setClientId(m_clientList.key(socket));
|
||||
reply->setPayload("403 Forbidden. File not readable");
|
||||
@ -388,8 +388,15 @@ void WebServer::readClient()
|
||||
|
||||
HttpReply *reply = NymeaCore::instance()->debugServerHandler()->processDebugRequest(request.url().path());
|
||||
reply->setClientId(clientId);
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
|
||||
// Handle async replies
|
||||
if (reply->type() == HttpReply::TypeAsync) {
|
||||
connect(reply, &HttpReply::finished, this, &WebServer::onAsyncReplyFinished);
|
||||
reply->startWait();
|
||||
} else {
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
qCWarning(dcWebServer()) << "The debug server handler is disabled. You can enable it by adding \'debugServerEnabled=true\' in the \'nymead\' section of the nymead.conf file.";
|
||||
@ -403,7 +410,7 @@ void WebServer::readClient()
|
||||
|
||||
// Check server.xml call
|
||||
if (request.url().path() == "/server.xml" && request.method() == HttpRequest::Get) {
|
||||
qCDebug(dcWebServer) << "server XML request call";
|
||||
qCDebug(dcWebServer) << "Server XML request call";
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/xml");
|
||||
reply->setPayload(createServerXmlDocument(socket->localAddress()));
|
||||
@ -418,7 +425,7 @@ void WebServer::readClient()
|
||||
if (request.method() == HttpRequest::Get) {
|
||||
// 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.";
|
||||
qCWarning(dcWebServer) << "Webinterface folder" << m_configuration.publicFolder << "does not exist.";
|
||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||
reply->setClientId(clientId);
|
||||
sendHttpReply(reply);
|
||||
@ -432,7 +439,7 @@ void WebServer::readClient()
|
||||
|
||||
QFile file(path);
|
||||
if (file.open(QFile::ReadOnly | QFile::Truncate)) {
|
||||
qCDebug(dcWebServer) << "load file" << file.fileName();
|
||||
qCDebug(dcWebServer) << "Load file" << file.fileName();
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
|
||||
// Check content type
|
||||
@ -522,6 +529,21 @@ void WebServer::onError(QAbstractSocket::SocketError error)
|
||||
qCWarning(dcWebServer()) << QString("Client socket error %1:%2 ->").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << socket->errorString();
|
||||
}
|
||||
|
||||
void WebServer::onAsyncReplyFinished()
|
||||
{
|
||||
HttpReply *reply = qobject_cast<HttpReply*>(sender());
|
||||
qCDebug(dcWebServer) << "Async reply finished";
|
||||
|
||||
// check if the reply timeouted
|
||||
if (reply->timedOut()) {
|
||||
reply->clear();
|
||||
reply->setHttpStatusCode(HttpReply::GatewayTimeout);
|
||||
}
|
||||
|
||||
sendHttpReply(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void WebServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
@ -826,7 +848,7 @@ void WebServerClient::removeConnection(QSslSocket *socket)
|
||||
*/
|
||||
void WebServerClient::resetTimout(QSslSocket *socket)
|
||||
{
|
||||
QTimer *timer = 0;
|
||||
QTimer *timer = nullptr;
|
||||
timer = m_runningConnections.key(socket);
|
||||
if (timer)
|
||||
timer->start();
|
||||
|
||||
@ -113,6 +113,7 @@ private slots:
|
||||
void onDisconnected();
|
||||
void onEncrypted();
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
void onAsyncReplyFinished();
|
||||
|
||||
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
|
||||
void resetAvahiService();
|
||||
|
||||