Update webserver debug output, add WebServerTraffic category and fix favicons for debugserver
This commit is contained in:
parent
b9dda16af9
commit
e51508ee33
@ -11,5 +11,18 @@
|
|||||||
<file>favicons/favicon-196x196.png</file>
|
<file>favicons/favicon-196x196.png</file>
|
||||||
<file>favicons/favicon.ico</file>
|
<file>favicons/favicon.ico</file>
|
||||||
<file>favicons/favicon.svg</file>
|
<file>favicons/favicon.svg</file>
|
||||||
|
<file>favicons/mstile-70x70.png</file>
|
||||||
|
<file>favicons/mstile-144x144.png</file>
|
||||||
|
<file>favicons/mstile-150x150.png</file>
|
||||||
|
<file>favicons/mstile-310x150.png</file>
|
||||||
|
<file>favicons/mstile-310x310.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-152x152.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-144x144.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-57x57.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-60x60.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-72x72.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-76x76.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-114x114.png</file>
|
||||||
|
<file>favicons/apple-touch-icon-120x120.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -161,7 +161,7 @@ HttpReply::HttpReply(QObject *parent) :
|
|||||||
setHeader(HttpHeaderType::CacheControlHeader, "no-cache");
|
setHeader(HttpHeaderType::CacheControlHeader, "no-cache");
|
||||||
setHeader(HttpHeaderType::ConnectionHeader, "Keep-Alive");
|
setHeader(HttpHeaderType::ConnectionHeader, "Keep-Alive");
|
||||||
setRawHeader("Access-Control-Allow-Origin","*");
|
setRawHeader("Access-Control-Allow-Origin","*");
|
||||||
setRawHeader("Keep-Alive", "timeout=12, max=50");
|
setRawHeader("Keep-Alive", QString("timeout=%1, max=50").arg(m_timeout).toUtf8());
|
||||||
packReply();
|
packReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ HttpReply::HttpReply(const HttpReply::HttpStatusCode &statusCode, const HttpRepl
|
|||||||
setHeader(HttpHeaderType::CacheControlHeader, "no-cache");
|
setHeader(HttpHeaderType::CacheControlHeader, "no-cache");
|
||||||
setHeader(HttpHeaderType::ConnectionHeader, "Keep-Alive");
|
setHeader(HttpHeaderType::ConnectionHeader, "Keep-Alive");
|
||||||
setRawHeader("Access-Control-Allow-Origin","*");
|
setRawHeader("Access-Control-Allow-Origin","*");
|
||||||
setRawHeader("Keep-Alive", "timeout=12, max=50");
|
setRawHeader("Keep-Alive", QString("timeout=%1, max=50").arg(m_timeout).toUtf8());
|
||||||
packReply();
|
packReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +326,7 @@ void HttpReply::packReply()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_rawHeader.append("\r\n");
|
m_rawHeader.append("\r\n");
|
||||||
m_data = m_rawHeader.append(m_payload);
|
m_data = QByteArray(m_rawHeader).append(m_payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns the current raw data (header + payload) of this \l{HttpReply}.*/
|
/*! Returns the current raw data (header + payload) of this \l{HttpReply}.*/
|
||||||
@ -343,72 +343,101 @@ bool HttpReply::timedOut() const
|
|||||||
|
|
||||||
QByteArray HttpReply::getHttpReasonPhrase(const HttpReply::HttpStatusCode &statusCode)
|
QByteArray HttpReply::getHttpReasonPhrase(const HttpReply::HttpStatusCode &statusCode)
|
||||||
{
|
{
|
||||||
|
QByteArray response;
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
case HttpStatusCode::Ok:
|
case HttpStatusCode::Ok:
|
||||||
return "Ok";
|
response = QString("Ok").toUtf8();
|
||||||
|
break;
|
||||||
case Created:
|
case Created:
|
||||||
return "Created";
|
response = QString("Created").toUtf8();
|
||||||
|
break;
|
||||||
case Accepted:
|
case Accepted:
|
||||||
return "Accepted";
|
response = QString("Accepted").toUtf8();
|
||||||
|
break;
|
||||||
case NoContent:
|
case NoContent:
|
||||||
return "No Content";
|
response = QString("No Content").toUtf8();
|
||||||
|
break;
|
||||||
case Found:
|
case Found:
|
||||||
return "Found";
|
response = QString("Found").toUtf8();
|
||||||
|
break;
|
||||||
case PermanentRedirect:
|
case PermanentRedirect:
|
||||||
return "Permanent Redirect";
|
response = QString("Permanent Redirect").toUtf8();
|
||||||
|
break;
|
||||||
case BadRequest:
|
case BadRequest:
|
||||||
return "Bad Request";
|
response = QString("Bad Request").toUtf8();
|
||||||
|
break;
|
||||||
case Forbidden:
|
case Forbidden:
|
||||||
return "Forbidden";
|
response = QString("Forbidden").toUtf8();
|
||||||
|
break;
|
||||||
case NotFound:
|
case NotFound:
|
||||||
return "NotFound";
|
response = QString("NotFound").toUtf8();
|
||||||
|
break;
|
||||||
case MethodNotAllowed:
|
case MethodNotAllowed:
|
||||||
return "Method Not Allowed";
|
response = QString("Method Not Allowed").toUtf8();
|
||||||
|
break;
|
||||||
case RequestTimeout:
|
case RequestTimeout:
|
||||||
return "Request Timeout";
|
response = QString("Request Timeout").toUtf8();
|
||||||
|
break;
|
||||||
case Conflict:
|
case Conflict:
|
||||||
return "Conflict";
|
response = QString("Conflict").toUtf8();
|
||||||
|
break;
|
||||||
case InternalServerError:
|
case InternalServerError:
|
||||||
return "Internal Server Error";
|
response = QString("Internal Server Error").toUtf8();
|
||||||
|
break;
|
||||||
case NotImplemented:
|
case NotImplemented:
|
||||||
return "Not Implemented";
|
response = QString("Not Implemented").toUtf8();
|
||||||
|
break;
|
||||||
case BadGateway:
|
case BadGateway:
|
||||||
return "Bad Gateway";
|
response = QString("Bad Gateway").toUtf8();
|
||||||
|
break;
|
||||||
case ServiceUnavailable:
|
case ServiceUnavailable:
|
||||||
return "Service Unavailable";
|
response = QString("Service Unavailable").toUtf8();
|
||||||
|
break;
|
||||||
case GatewayTimeout:
|
case GatewayTimeout:
|
||||||
return "Gateway Timeout";
|
response = QString("Gateway Timeout").toUtf8();
|
||||||
|
break;
|
||||||
case HttpVersionNotSupported:
|
case HttpVersionNotSupported:
|
||||||
return "HTTP Version Not Supported";
|
response = QString("HTTP Version Not Supported").toUtf8();
|
||||||
default:
|
break;
|
||||||
return QByteArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType)
|
QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType)
|
||||||
{
|
{
|
||||||
|
QByteArray header;
|
||||||
switch (headerType) {
|
switch (headerType) {
|
||||||
case ContentTypeHeader:
|
case ContentTypeHeader:
|
||||||
return "Content-Type";
|
header = QString("Content-Type").toUtf8();
|
||||||
|
break;
|
||||||
case ContentLenghtHeader:
|
case ContentLenghtHeader:
|
||||||
return "Content-Length";
|
header = QString("Content-Length").toUtf8();
|
||||||
|
break;
|
||||||
case CacheControlHeader:
|
case CacheControlHeader:
|
||||||
return "Cache-Control";
|
header = QString("Cache-Control").toUtf8();
|
||||||
|
break;
|
||||||
case LocationHeader:
|
case LocationHeader:
|
||||||
return "Location";
|
header = QString("Location").toUtf8();
|
||||||
|
break;
|
||||||
case ConnectionHeader:
|
case ConnectionHeader:
|
||||||
return "Connection";
|
header = QString("Connection").toUtf8();
|
||||||
|
break;
|
||||||
case UserAgentHeader:
|
case UserAgentHeader:
|
||||||
return "User-Agent";
|
header = QString("User-Agent").toUtf8();
|
||||||
|
break;
|
||||||
case AllowHeader:
|
case AllowHeader:
|
||||||
return "Allow";
|
header = QString("Allow").toUtf8();
|
||||||
|
break;
|
||||||
case DateHeader:
|
case DateHeader:
|
||||||
return "Date";
|
header = QString("Date").toUtf8();
|
||||||
|
break;
|
||||||
case ServerHeader:
|
case ServerHeader:
|
||||||
return "Server";
|
header = QString("Server").toUtf8();
|
||||||
default:
|
break;
|
||||||
return QByteArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Starts the timer for an async \l{HttpReply}.
|
/*! Starts the timer for an async \l{HttpReply}.
|
||||||
@ -417,24 +446,22 @@ QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType)
|
|||||||
*/
|
*/
|
||||||
void HttpReply::startWait()
|
void HttpReply::startWait()
|
||||||
{
|
{
|
||||||
m_timer->start(60000);
|
m_timer->start(m_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpReply::timeout()
|
void HttpReply::timeout()
|
||||||
{
|
{
|
||||||
qCDebug(dcWebServer) << "Http reply timeout";
|
qCDebug(dcWebServer()) << "Http reply timeout";
|
||||||
m_timedOut = true;
|
m_timedOut = true;
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const HttpReply &httpReply)
|
QDebug operator<<(QDebug debug, HttpReply *httpReply)
|
||||||
{
|
{
|
||||||
debug << "-----------------------------------" << "\n";
|
debug.nospace() << "HttpReply(" << httpReply->clientId().toString() << ")" << endl;
|
||||||
debug << httpReply.rawHeader() << "\n";
|
debug << qUtf8Printable(httpReply->rawHeader());
|
||||||
debug << "-----------------------------------" << "\n";
|
debug << qUtf8Printable(httpReply->payload());
|
||||||
debug << httpReply.payload() << "\n";
|
return debug.space();
|
||||||
debug << "-----------------------------------" << "\n";
|
|
||||||
return debug;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,7 +121,8 @@ private:
|
|||||||
|
|
||||||
bool m_closeConnection;
|
bool m_closeConnection;
|
||||||
|
|
||||||
QTimer *m_timer;
|
QTimer *m_timer = nullptr;
|
||||||
|
int m_timeout = 60000;
|
||||||
bool m_timedOut;
|
bool m_timedOut;
|
||||||
|
|
||||||
QByteArray getHttpReasonPhrase(const HttpStatusCode &statusCode);
|
QByteArray getHttpReasonPhrase(const HttpStatusCode &statusCode);
|
||||||
@ -138,7 +139,7 @@ signals:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QDebug operator<< (QDebug debug, const HttpReply &httpReply);
|
QDebug operator<<(QDebug debug, HttpReply *httpReply);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -172,7 +172,7 @@ void HttpRequest::validate()
|
|||||||
// split the data into header and payload
|
// split the data into header and payload
|
||||||
int headerEndIndex = m_rawData.indexOf("\r\n\r\n");
|
int headerEndIndex = m_rawData.indexOf("\r\n\r\n");
|
||||||
if (headerEndIndex < 0) {
|
if (headerEndIndex < 0) {
|
||||||
qCWarning(dcWebServer) << "Could not parse end of HTTP header (empty line between header and body):" << m_rawData;
|
qCWarning(dcWebServer()) << "Could not parse end of HTTP header (empty line between header and body):" << m_rawData;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,14 +184,14 @@ void HttpRequest::validate()
|
|||||||
QString statusLine = headerLines.takeFirst();
|
QString statusLine = headerLines.takeFirst();
|
||||||
QStringList statusLineTokens = statusLine.split(QRegExp("[ \r\n][ \r\n]*"));
|
QStringList statusLineTokens = statusLine.split(QRegExp("[ \r\n][ \r\n]*"));
|
||||||
if (statusLineTokens.count() != 3) {
|
if (statusLineTokens.count() != 3) {
|
||||||
qCWarning(dcWebServer) << "Could not parse HTTP status line:" << statusLine;
|
qCWarning(dcWebServer()) << "Could not parse HTTP status line:" << statusLine;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify http version
|
// verify http version
|
||||||
m_httpVersion = statusLineTokens.at(2).toUtf8().simplified();
|
m_httpVersion = statusLineTokens.at(2).toUtf8().simplified();
|
||||||
if (!m_httpVersion.contains("HTTP")) {
|
if (!m_httpVersion.contains("HTTP")) {
|
||||||
qCWarning(dcWebServer) << "Unknown HTTP version:" << m_httpVersion;
|
qCWarning(dcWebServer()) << "Unknown HTTP version:" << m_httpVersion;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_methodString = statusLineTokens.at(0).simplified();
|
m_methodString = statusLineTokens.at(0).simplified();
|
||||||
@ -205,7 +205,7 @@ void HttpRequest::validate()
|
|||||||
// verify header formating
|
// verify header formating
|
||||||
foreach (const QString &line, headerLines) {
|
foreach (const QString &line, headerLines) {
|
||||||
if (!line.contains(":")) {
|
if (!line.contains(":")) {
|
||||||
qCWarning(dcWebServer) << "Invalid HTTP header:" << line;
|
qCWarning(dcWebServer()) << "Invalid HTTP header:" << line;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int index = line.indexOf(":");
|
int index = line.indexOf(":");
|
||||||
@ -216,7 +216,7 @@ void HttpRequest::validate()
|
|||||||
|
|
||||||
// check User-Agent
|
// check User-Agent
|
||||||
if (!m_rawHeaderList.contains("User-Agent"))
|
if (!m_rawHeaderList.contains("User-Agent"))
|
||||||
qCWarning(dcWebServer) << "User-Agent header is missing";
|
qCWarning(dcWebServer()) << "User-Agent header is missing";
|
||||||
|
|
||||||
|
|
||||||
// verify content length with actual payload
|
// verify content length with actual payload
|
||||||
@ -224,22 +224,22 @@ void HttpRequest::validate()
|
|||||||
bool ok = false;
|
bool ok = false;
|
||||||
int contentLength = m_rawHeaderList.value("Content-Length").toInt(&ok);
|
int contentLength = m_rawHeaderList.value("Content-Length").toInt(&ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
qCWarning(dcWebServer) << "Could not parse Content-Length.";
|
qCWarning(dcWebServer()) << "Could not parse Content-Length.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// check if we have all data
|
// check if we have all data
|
||||||
if (m_payload.size() < contentLength) {
|
if (m_payload.size() < contentLength) {
|
||||||
qCDebug(dcWebServer) << "Request incomplete:";
|
qCDebug(dcWebServer()) << "Request incomplete:";
|
||||||
qCDebug(dcWebServer) << " -> Content-Length:" << contentLength;
|
qCDebug(dcWebServer()) << " -> Content-Length:" << contentLength;
|
||||||
qCDebug(dcWebServer) << " -> Payload size :" << payload().size();
|
qCDebug(dcWebServer()) << " -> Payload size :" << payload().size();
|
||||||
m_isComplete = false;
|
m_isComplete = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// check if the content length bigger than header Content-Length
|
// check if the content length bigger than header Content-Length
|
||||||
if (m_payload.size() > contentLength) {
|
if (m_payload.size() > contentLength) {
|
||||||
qCWarning(dcWebServer) << "Payload size greater than header Content-Length:";
|
qCWarning(dcWebServer()) << "Payload size greater than header Content-Length:";
|
||||||
qCWarning(dcWebServer) << " -> Content-Length:" << contentLength;
|
qCWarning(dcWebServer()) << " -> Content-Length:" << contentLength;
|
||||||
qCWarning(dcWebServer) << " -> Payload size :" << payload().size();
|
qCWarning(dcWebServer()) << " -> Payload size :" << payload().size();
|
||||||
m_isComplete = true;
|
m_isComplete = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -261,23 +261,15 @@ HttpRequest::RequestMethod HttpRequest::getRequestMethodType(const QString &meth
|
|||||||
} else if (methodString == "OPTIONS") {
|
} else if (methodString == "OPTIONS") {
|
||||||
return RequestMethod::Options;
|
return RequestMethod::Options;
|
||||||
}
|
}
|
||||||
qCWarning(dcWebServer) << "Method" << methodString << "will not be handled.";
|
qCWarning(dcWebServer()) << "Method" << methodString << "will not be handled.";
|
||||||
return RequestMethod::Unhandled;
|
return RequestMethod::Unhandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const HttpRequest &httpRequest)
|
QDebug operator<<(QDebug debug, const HttpRequest &httpRequest)
|
||||||
{
|
{
|
||||||
debug << "===================================" << "\n";
|
debug << "HttpRequest:" << endl;
|
||||||
debug << " HTTP version: " << httpRequest.httpVersion() << "\n";
|
debug << qUtf8Printable(httpRequest.rawHeader());
|
||||||
debug << " method: " << httpRequest.methodString() << "\n";
|
debug << qUtf8Printable(httpRequest.payload());
|
||||||
debug << " URL path: " << httpRequest.url().path() << "\n";
|
|
||||||
debug << " URL query: " << httpRequest.urlQuery().query() << "\n";
|
|
||||||
debug << " is valid: " << httpRequest.isValid() << "\n";
|
|
||||||
debug << "-----------------------------------" << "\n";
|
|
||||||
debug << httpRequest.rawHeader() << "\n";
|
|
||||||
debug << "-----------------------------------" << "\n";
|
|
||||||
debug << httpRequest.payload() << "\n";
|
|
||||||
debug << "-----------------------------------" << "\n";
|
|
||||||
return debug;
|
return debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -151,7 +151,7 @@ void RestServer::asyncReplyFinished()
|
|||||||
HttpReply *reply = qobject_cast<HttpReply*>(sender());
|
HttpReply *reply = qobject_cast<HttpReply*>(sender());
|
||||||
|
|
||||||
if (!m_asyncReplies.values().contains(reply)) {
|
if (!m_asyncReplies.values().contains(reply)) {
|
||||||
qCWarning(dcWebServer) << "Reply for async request does no longer exist";
|
qCWarning(dcWebServer()) << "Reply for async request does no longer exist";
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ void RestServer::asyncReplyFinished()
|
|||||||
QUuid clientId = m_asyncReplies.key(reply);
|
QUuid clientId = m_asyncReplies.key(reply);
|
||||||
m_asyncReplies.remove(clientId);
|
m_asyncReplies.remove(clientId);
|
||||||
|
|
||||||
qCDebug(dcWebServer) << "Async reply finished";
|
qCDebug(dcWebServer()) << "Async reply finished";
|
||||||
|
|
||||||
// check if the reply timeouted
|
// check if the reply timeouted
|
||||||
if (reply->timedOut()) {
|
if (reply->timedOut()) {
|
||||||
@ -169,7 +169,7 @@ void RestServer::asyncReplyFinished()
|
|||||||
|
|
||||||
// check if client is still connected
|
// check if client is still connected
|
||||||
if (!m_clientList.contains(clientId)) {
|
if (!m_clientList.contains(clientId)) {
|
||||||
qCWarning(dcWebServer) << "Client for async reply not longer connected.";
|
qCWarning(dcWebServer()) << "Client for async reply not longer connected.";
|
||||||
} else {
|
} else {
|
||||||
reply->setClientId(clientId);
|
reply->setClientId(clientId);
|
||||||
WebServer *webserver = m_clientList.value(clientId);
|
WebServer *webserver = m_clientList.value(clientId);
|
||||||
|
|||||||
@ -105,7 +105,7 @@ WebServer::WebServer(const WebServerConfiguration &configuration, const QSslConf
|
|||||||
if (QCoreApplication::instance()->organizationName() == "nymea-test") {
|
if (QCoreApplication::instance()->organizationName() == "nymea-test") {
|
||||||
m_configuration.publicFolder = QCoreApplication::applicationDirPath();
|
m_configuration.publicFolder = QCoreApplication::applicationDirPath();
|
||||||
}
|
}
|
||||||
qCDebug(dcWebServer) << "Starting WebServer. Interface:" << m_configuration.address << "Port:" << m_configuration.port << "SSL:" << m_configuration.sslEnabled << "AUTH:" << m_configuration.authenticationEnabled << "Public folder:" << QDir(m_configuration.publicFolder).canonicalPath();
|
qCDebug(dcWebServer()) << "Starting WebServer. Interface:" << m_configuration.address << "Port:" << m_configuration.port << "SSL:" << m_configuration.sslEnabled << "AUTH:" << m_configuration.authenticationEnabled << "Public folder:" << QDir(m_configuration.publicFolder).canonicalPath();
|
||||||
|
|
||||||
m_avahiService = new QtAvahiService(this);
|
m_avahiService = new QtAvahiService(this);
|
||||||
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &WebServer::onAvahiServiceStateChanged);
|
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &WebServer::onAvahiServiceStateChanged);
|
||||||
@ -135,13 +135,14 @@ void WebServer::sendHttpReply(HttpReply *reply)
|
|||||||
QSslSocket *socket = nullptr;
|
QSslSocket *socket = nullptr;
|
||||||
socket = m_clientList.value(reply->clientId());
|
socket = m_clientList.value(reply->clientId());
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
qCWarning(dcWebServer) << "Invalid socket pointer! This should never happen!!! Missing clientId in reply?";
|
qCWarning(dcWebServer()) << "Invalid socket pointer! This should never happen!!! Missing clientId in reply?";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send raw data
|
// send raw data
|
||||||
reply->packReply();
|
reply->packReply();
|
||||||
qCDebug(dcWebServer) << "Respond" << reply->httpStatusCode() << reply->httpReasonPhrase();
|
qCDebug(dcWebServerTraffic()) << "Send reply to" << socket->peerAddress().toString() << reply;
|
||||||
|
qCDebug(dcWebServer()) << "Respond" << socket->peerAddress().toString() << reply->httpStatusCode() << reply->httpReasonPhrase();
|
||||||
socket->write(reply->data());
|
socket->write(reply->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
|||||||
|
|
||||||
// make sure the file exists
|
// make sure the file exists
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
qCWarning(dcWebServer) << "requested file" << file.filePath() << "does not exist.";
|
qCWarning(dcWebServer()) << "requested file" << file.filePath() << "does not exist.";
|
||||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||||
reply->setClientId(m_clientList.key(socket));
|
reply->setClientId(m_clientList.key(socket));
|
||||||
sendHttpReply(reply);
|
sendHttpReply(reply);
|
||||||
@ -161,7 +162,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
|||||||
|
|
||||||
// make sure the file is in the public directory
|
// make sure the file is in the public directory
|
||||||
if (!file.canonicalFilePath().startsWith(QDir(m_configuration.publicFolder).canonicalPath())) {
|
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);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||||
reply->setClientId(m_clientList.key(socket));
|
reply->setClientId(m_clientList.key(socket));
|
||||||
sendHttpReply(reply);
|
sendHttpReply(reply);
|
||||||
@ -171,7 +172,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
|||||||
|
|
||||||
// make sure we can read the file
|
// make sure we can read the file
|
||||||
if (!file.isReadable()) {
|
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);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden);
|
||||||
reply->setClientId(m_clientList.key(socket));
|
reply->setClientId(m_clientList.key(socket));
|
||||||
reply->setPayload("403 Forbidden. File not readable");
|
reply->setPayload("403 Forbidden. File not readable");
|
||||||
@ -234,7 +235,7 @@ void WebServer::incomingConnection(qintptr socketDescriptor)
|
|||||||
foreach (WebServerClient *client, m_webServerClients) {
|
foreach (WebServerClient *client, m_webServerClients) {
|
||||||
if (client->address() == socket->peerAddress()) {
|
if (client->address() == socket->peerAddress()) {
|
||||||
if (client->connections().count() >= 50) {
|
if (client->connections().count() >= 50) {
|
||||||
qCWarning(dcWebServer()) << QString("Maximum connections for this client reached: rejecting connection from client %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCWarning(dcWebServer()).noquote() << QString("Maximum connections for this client reached: rejecting connection from client %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
socket->close();
|
socket->close();
|
||||||
delete socket;
|
delete socket;
|
||||||
return;
|
return;
|
||||||
@ -255,7 +256,7 @@ void WebServer::incomingConnection(qintptr socketDescriptor)
|
|||||||
QUuid clientId = QUuid::createUuid();
|
QUuid clientId = QUuid::createUuid();
|
||||||
m_clientList.insert(clientId, socket);
|
m_clientList.insert(clientId, socket);
|
||||||
|
|
||||||
qCDebug(dcWebServer()) << QString("Webserver client %1:%2 connected").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCDebug(dcWebServer()).noquote() << QString("Webserver client %1:%2 connected").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
|
|
||||||
if (m_configuration.sslEnabled) {
|
if (m_configuration.sslEnabled) {
|
||||||
// configure client connection
|
// configure client connection
|
||||||
@ -283,7 +284,7 @@ void WebServer::readClient()
|
|||||||
|
|
||||||
// Check client
|
// Check client
|
||||||
if (clientId.isNull()) {
|
if (clientId.isNull()) {
|
||||||
qCWarning(dcWebServer) << "Client not recognized";
|
qCWarning(dcWebServer()) << "Client not recognized";
|
||||||
socket->close();
|
socket->close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -293,7 +294,7 @@ void WebServer::readClient()
|
|||||||
|
|
||||||
HttpRequest request;
|
HttpRequest request;
|
||||||
if (m_incompleteRequests.contains(socket)) {
|
if (m_incompleteRequests.contains(socket)) {
|
||||||
qCDebug(dcWebServer) << "Append data to incomlete request";
|
qCDebug(dcWebServer()) << "Append data to incomlete request";
|
||||||
request = m_incompleteRequests.take(socket);
|
request = m_incompleteRequests.take(socket);
|
||||||
request.appendData(data);
|
request.appendData(data);
|
||||||
} else {
|
} else {
|
||||||
@ -306,9 +307,11 @@ void WebServer::readClient()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qCDebug(dcWebServerTraffic()) << "Received request from" << clientId.toString() << socket->peerAddress().toString() << request;
|
||||||
|
|
||||||
// Check if the request is valid
|
// Check if the request is valid
|
||||||
if (!request.isValid()) {
|
if (!request.isValid()) {
|
||||||
qCWarning(dcWebServer) << "Got invalid request:" << request.url().path();
|
qCWarning(dcWebServer()) << "Got invalid request:" << request.url().path();
|
||||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest);
|
||||||
reply->setClientId(clientId);
|
reply->setClientId(clientId);
|
||||||
sendHttpReply(reply);
|
sendHttpReply(reply);
|
||||||
@ -318,7 +321,7 @@ void WebServer::readClient()
|
|||||||
|
|
||||||
// Check HTTP version
|
// Check HTTP version
|
||||||
if (request.httpVersion() != "HTTP/1.1" && request.httpVersion() != "HTTP/1.0") {
|
if (request.httpVersion() != "HTTP/1.1" && request.httpVersion() != "HTTP/1.0") {
|
||||||
qCWarning(dcWebServer) << "HTTP version is not supported." << request.httpVersion();
|
qCWarning(dcWebServer()) << "HTTP version is not supported." << request.httpVersion();
|
||||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::HttpVersionNotSupported);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::HttpVersionNotSupported);
|
||||||
reply->setClientId(clientId);
|
reply->setClientId(clientId);
|
||||||
sendHttpReply(reply);
|
sendHttpReply(reply);
|
||||||
@ -326,8 +329,7 @@ void WebServer::readClient()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcWebServer) << QString("Got valid request from %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCDebug(dcWebServer()).noquote() << QString("Got valid request from %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << request.methodString() << request.url().path() << request.urlQuery().toString();
|
||||||
qCDebug(dcWebServer) << request.methodString() << request.url().path();
|
|
||||||
|
|
||||||
// Reset timout
|
// Reset timout
|
||||||
foreach (WebServerClient *webserverClient, m_webServerClients) {
|
foreach (WebServerClient *webserverClient, m_webServerClients) {
|
||||||
@ -410,7 +412,7 @@ void WebServer::readClient()
|
|||||||
|
|
||||||
// Check server.xml call
|
// Check server.xml call
|
||||||
if (request.url().path() == "/server.xml" && request.method() == HttpRequest::Get) {
|
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();
|
HttpReply *reply = RestResource::createSuccessReply();
|
||||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/xml");
|
reply->setHeader(HttpReply::ContentTypeHeader, "text/xml");
|
||||||
reply->setPayload(createServerXmlDocument(socket->localAddress()));
|
reply->setPayload(createServerXmlDocument(socket->localAddress()));
|
||||||
@ -424,8 +426,9 @@ void WebServer::readClient()
|
|||||||
// Request for a file...
|
// Request for a file...
|
||||||
if (request.method() == HttpRequest::Get) {
|
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
|
||||||
|
// FIXME: return a default webpage containing server information
|
||||||
if (!QDir(m_configuration.publicFolder).exists()) {
|
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);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound);
|
||||||
reply->setClientId(clientId);
|
reply->setClientId(clientId);
|
||||||
sendHttpReply(reply);
|
sendHttpReply(reply);
|
||||||
@ -439,7 +442,7 @@ void WebServer::readClient()
|
|||||||
|
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
if (file.open(QFile::ReadOnly | QFile::Truncate)) {
|
if (file.open(QFile::ReadOnly | QFile::Truncate)) {
|
||||||
qCDebug(dcWebServer) << "Load file" << file.fileName();
|
qCDebug(dcWebServer()) << "Load file" << file.fileName();
|
||||||
HttpReply *reply = RestResource::createSuccessReply();
|
HttpReply *reply = RestResource::createSuccessReply();
|
||||||
|
|
||||||
// Check content type
|
// Check content type
|
||||||
@ -476,7 +479,7 @@ void WebServer::readClient()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reject everything else...
|
// Reject everything else...
|
||||||
qCWarning(dcWebServer) << "Unknown message received.";
|
qCWarning(dcWebServer()) << "Unknown message received.";
|
||||||
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotImplemented);
|
HttpReply *reply = RestResource::createErrorReply(HttpReply::NotImplemented);
|
||||||
reply->setClientId(clientId);
|
reply->setClientId(clientId);
|
||||||
sendHttpReply(reply);
|
sendHttpReply(reply);
|
||||||
@ -492,7 +495,7 @@ void WebServer::onDisconnected()
|
|||||||
if (client->address() == socket->peerAddress()) {
|
if (client->address() == socket->peerAddress()) {
|
||||||
client->removeConnection(socket);
|
client->removeConnection(socket);
|
||||||
if (client->connections().isEmpty()) {
|
if (client->connections().isEmpty()) {
|
||||||
qCDebug(dcWebServer) << "Delete client" << client->address().toString();
|
qCDebug(dcWebServer()) << "Delete client" << client->address().toString();
|
||||||
m_webServerClients.removeAll(client);
|
m_webServerClients.removeAll(client);
|
||||||
client->deleteLater();
|
client->deleteLater();
|
||||||
}
|
}
|
||||||
@ -500,7 +503,7 @@ void WebServer::onDisconnected()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcWebServer) << QString("Webserver client disonnected %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCDebug(dcWebServer()).noquote() << QString("Webserver client disonnected %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
QUuid clientId = m_clientList.key(socket);
|
QUuid clientId = m_clientList.key(socket);
|
||||||
@ -514,7 +517,7 @@ void WebServer::onDisconnected()
|
|||||||
void WebServer::onEncrypted()
|
void WebServer::onEncrypted()
|
||||||
{
|
{
|
||||||
QSslSocket* socket = static_cast<QSslSocket *>(sender());
|
QSslSocket* socket = static_cast<QSslSocket *>(sender());
|
||||||
qCDebug(dcWebServer()) << QString("Encrypted connection %1:%2 successfully established.").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCDebug(dcWebServer()).noquote() << QString("Encrypted connection %1:%2 successfully established.").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readClient()));
|
connect(socket, SIGNAL(readyRead()), this, SLOT(readClient()));
|
||||||
connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
|
connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
|
||||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||||
@ -524,15 +527,21 @@ void WebServer::onEncrypted()
|
|||||||
|
|
||||||
void WebServer::onError(QAbstractSocket::SocketError error)
|
void WebServer::onError(QAbstractSocket::SocketError error)
|
||||||
{
|
{
|
||||||
Q_UNUSED(error)
|
|
||||||
QSslSocket* socket = static_cast<QSslSocket *>(sender());
|
QSslSocket* socket = static_cast<QSslSocket *>(sender());
|
||||||
qCWarning(dcWebServer()) << QString("Client socket error %1:%2 ->").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << socket->errorString();
|
switch (error) {
|
||||||
|
case QAbstractSocket::RemoteHostClosedError:
|
||||||
|
qCDebug(dcWebServer()).noquote() << QString("Client socket error %1:%2 ->").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << socket->errorString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCWarning(dcWebServer()).noquote() << QString("Client socket error %1:%2 ->").arg(socket->peerAddress().toString()).arg(socket->peerPort()) << socket->errorString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebServer::onAsyncReplyFinished()
|
void WebServer::onAsyncReplyFinished()
|
||||||
{
|
{
|
||||||
HttpReply *reply = qobject_cast<HttpReply*>(sender());
|
HttpReply *reply = qobject_cast<HttpReply*>(sender());
|
||||||
qCDebug(dcWebServer) << "Async reply finished";
|
qCDebug(dcWebServer()) << "Async reply finished";
|
||||||
|
|
||||||
// check if the reply timeouted
|
// check if the reply timeouted
|
||||||
if (reply->timedOut()) {
|
if (reply->timedOut()) {
|
||||||
@ -818,13 +827,13 @@ QList<QSslSocket *> WebServerClient::connections()
|
|||||||
|
|
||||||
/*! Adds a new connection (\a socket) to this \l{WebServerClient}. A \l{WebServerClient}
|
/*! Adds a new connection (\a socket) to this \l{WebServerClient}. A \l{WebServerClient}
|
||||||
* can have up to 50 connecections. The connection will timout and closed if the client
|
* can have up to 50 connecections. The connection will timout and closed if the client
|
||||||
* does not use the connection for 12 seconds.
|
* does not use the connection for 65 seconds.
|
||||||
*/
|
*/
|
||||||
void WebServerClient::addConnection(QSslSocket *socket)
|
void WebServerClient::addConnection(QSslSocket *socket)
|
||||||
{
|
{
|
||||||
QTimer *timer = new QTimer(this);
|
QTimer *timer = new QTimer(this);
|
||||||
timer->setSingleShot(true);
|
timer->setSingleShot(true);
|
||||||
timer->setInterval(12000);
|
timer->setInterval(65000);
|
||||||
connect(timer, &QTimer::timeout, this, &WebServerClient::onTimout);
|
connect(timer, &QTimer::timeout, this, &WebServerClient::onTimout);
|
||||||
|
|
||||||
m_runningConnections.insert(timer, socket);
|
m_runningConnections.insert(timer, socket);
|
||||||
@ -858,7 +867,8 @@ void WebServerClient::onTimout()
|
|||||||
{
|
{
|
||||||
QTimer *timer = static_cast<QTimer *>(sender());
|
QTimer *timer = static_cast<QTimer *>(sender());
|
||||||
QSslSocket *socket = m_runningConnections.value(timer);
|
QSslSocket *socket = m_runningConnections.value(timer);
|
||||||
qCDebug(dcWebServer) << QString("Client connection timout %1:%2 -> closing connection").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCDebug(dcWebServer()).noquote() << QString("Client connection timout %1:%2 -> closing connection").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
|
removeConnection(socket);
|
||||||
socket->close();
|
socket->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,7 @@ Q_LOGGING_CATEGORY(dcLogEngine, "LogEngine")
|
|||||||
Q_LOGGING_CATEGORY(dcTcpServer, "TcpServer")
|
Q_LOGGING_CATEGORY(dcTcpServer, "TcpServer")
|
||||||
Q_LOGGING_CATEGORY(dcTcpServerTraffic, "TcpServerTraffic")
|
Q_LOGGING_CATEGORY(dcTcpServerTraffic, "TcpServerTraffic")
|
||||||
Q_LOGGING_CATEGORY(dcWebServer, "WebServer")
|
Q_LOGGING_CATEGORY(dcWebServer, "WebServer")
|
||||||
|
Q_LOGGING_CATEGORY(dcWebServerTraffic, "WebServerTraffic")
|
||||||
Q_LOGGING_CATEGORY(dcDebugServer, "DebugServer")
|
Q_LOGGING_CATEGORY(dcDebugServer, "DebugServer")
|
||||||
Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
Q_LOGGING_CATEGORY(dcWebSocketServer, "WebSocketServer")
|
||||||
Q_LOGGING_CATEGORY(dcWebSocketServerTraffic, "WebSocketServerTraffic")
|
Q_LOGGING_CATEGORY(dcWebSocketServerTraffic, "WebSocketServerTraffic")
|
||||||
|
|||||||
@ -41,6 +41,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcLogEngine)
|
|||||||
Q_DECLARE_LOGGING_CATEGORY(dcTcpServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcTcpServer)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcTcpServerTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcTcpServerTraffic)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcWebServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcWebServer)
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(dcWebServerTraffic)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcDebugServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcDebugServer)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
|
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServer)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServerTraffic)
|
Q_DECLARE_LOGGING_CATEGORY(dcWebSocketServerTraffic)
|
||||||
|
|||||||
@ -111,6 +111,7 @@ int main(int argc, char *argv[])
|
|||||||
"TcpServer",
|
"TcpServer",
|
||||||
"TcpServerTraffic",
|
"TcpServerTraffic",
|
||||||
"WebServer",
|
"WebServer",
|
||||||
|
"WebServerTraffic",
|
||||||
"DebugServer",
|
"DebugServer",
|
||||||
"WebSocketServer",
|
"WebSocketServer",
|
||||||
"WebSocketServerTraffic",
|
"WebSocketServerTraffic",
|
||||||
|
|||||||
Reference in New Issue
Block a user