From 01f9b418a9c0438e3675c3b000bfc2fc02a09270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 28 Aug 2015 14:44:34 +0200 Subject: [PATCH] fix replies from webserver --- server/httpreply.cpp | 5 +- server/rest/restresource.cpp | 4 +- server/rest/restserver.cpp | 5 +- server/webserver.cpp | 89 ++++++++++++---------- server/webserver.h | 2 - tests/auto/restdevices/testrestdevices.cpp | 2 +- tests/auto/webserver/testwebserver.cpp | 4 +- 7 files changed, 62 insertions(+), 49 deletions(-) diff --git a/server/httpreply.cpp b/server/httpreply.cpp index e71305ce..1d95e749 100644 --- a/server/httpreply.cpp +++ b/server/httpreply.cpp @@ -139,7 +139,7 @@ HttpReply::HttpReply(QObject *parent) : setRawHeader("Access-Control-Allow-Origin","*"); setRawHeader("Keep-Alive", "timeout=6, max=50"); setHeader(HttpHeaderType::CacheControlHeader, "no-cache"); - setHeader(HttpHeaderType::ConnectionHeader, "Keep-Alive"); + setHeader(HttpHeaderType::ConnectionHeader, "keep-alive"); packReply(); } @@ -275,6 +275,9 @@ bool HttpReply::isEmpty() const /*! Clears all data of this \l{HttpReply}. */ void HttpReply::clear() { + m_closeConnection = false; + m_type = TypeSync; + m_statusCode = Ok; m_rawHeader.clear(); m_payload.clear(); m_rawHeaderList.clear(); diff --git a/server/rest/restresource.cpp b/server/rest/restresource.cpp index b42b17f7..0e7c2143 100644 --- a/server/rest/restresource.cpp +++ b/server/rest/restresource.cpp @@ -90,10 +90,12 @@ HttpReply *RestResource::createCorsSuccessReply() { HttpReply *reply = RestResource::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); + reply->setRawHeader("Accept","text/plain"); + reply->setRawHeader("Allow", "PUT, POST, GET, DELETE, OPTIONS"); reply->setRawHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS"); reply->setRawHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept"); reply->setRawHeader("Access-Control-Max-Age", "1728000"); - reply->setCloseConnection(true); + //reply->setCloseConnection(true); return reply; } diff --git a/server/rest/restserver.cpp b/server/rest/restserver.cpp index 87b73a67..490fce59 100644 --- a/server/rest/restserver.cpp +++ b/server/rest/restserver.cpp @@ -116,6 +116,7 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re qCDebug(dcRest) << "process options request\n" << request; HttpReply *reply = RestResource::createCorsSuccessReply(); reply->setClientId(clientId); + qCDebug(dcRest) << reply->data(); m_webserver->sendHttpReply(reply); reply->deleteLater(); return; @@ -142,8 +143,10 @@ void RestServer::asyncReplyFinished() qCDebug(dcWebServer) << "Async reply finished"; - if (reply->timedOut()) + if (reply->timedOut()) { + reply->clear(); reply->setHttpStatusCode(HttpReply::GatewayTimeout); + } m_webserver->sendHttpReply(reply); reply->deleteLater(); diff --git a/server/webserver.cpp b/server/webserver.cpp index 51750011..a8ab288d 100644 --- a/server/webserver.cpp +++ b/server/webserver.cpp @@ -75,6 +75,7 @@ #include "guhsettings.h" #include "httpreply.h" #include "httprequest.h" +#include "rest/restresource.h" #include #include @@ -130,15 +131,19 @@ WebServer::~WebServer() */ void WebServer::sendHttpReply(HttpReply *reply) { + // get the right socket QSslSocket *socket = 0; socket = m_clientList.value(reply->clientId()); if (!socket) { - qCDebug(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; } - //qCDebug(dcWebServer()) << "sending header to" << socket->peerAddress().toString() << socket->peerPort() << "\n" << reply->rawHeader(); - writeData(socket, reply->data()); + // send raw data + reply->packReply(); + socket->write(reply->data()); + + // close the connection if wanted if (reply->closeConnection()) socket->close(); @@ -151,30 +156,31 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName) // make shore the file exists if (!file.exists()) { qCWarning(dcWebServer) << "requested file" << file.filePath() << "does not exist."; - HttpReply reply(HttpReply::NotFound); - reply.setPayload("404 Not found."); - reply.packReply(); - writeData(socket, reply.data()); + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + reply->setClientId(m_clientList.key(socket)); + sendHttpReply(reply); + reply->deleteLater(); return false; } // make shore the file is in the public directory if (!file.canonicalFilePath().startsWith(m_webinterfaceDir.path())) { qCWarning(dcWebServer) << "requested file" << file.fileName() << "is outside the public folder."; - HttpReply reply(HttpReply::Forbidden); - reply.setPayload("403 Forbidden."); - reply.packReply(); - writeData(socket, reply.data()); + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setClientId(m_clientList.key(socket)); + sendHttpReply(reply); + reply->deleteLater(); return false; } // make shore we can read the file if (!file.isReadable()) { qCWarning(dcWebServer) << "requested file" << file.fileName() << "is not readable."; - HttpReply reply(HttpReply::Forbidden); - reply.setPayload("403 Forbidden. Page not readable."); - reply.packReply(); - writeData(socket, reply.data()); + HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + reply->setClientId(m_clientList.key(socket)); + reply->setPayload("403 Forbidden. File not readable"); + sendHttpReply(reply); + reply->deleteLater(); return false; } return true; @@ -192,11 +198,6 @@ QString WebServer::fileName(const QString &query) return m_webinterfaceDir.path() + fileName; } -void WebServer::writeData(QSslSocket *socket, const QByteArray &data) -{ - socket->write(data + "\r\n"); -} - void WebServer::incomingConnection(qintptr socketDescriptor) { if (!m_enabled) @@ -283,25 +284,29 @@ void WebServer::readClient() request = HttpRequest(data); } + // check if the request is complete if (!request.isComplete()) { m_incompleteRequests.insert(socket, request); return; } + // check if the request is valid if (!request.isValid()) { qCWarning(dcWebServer) << "Got invalid request."; - HttpReply reply(HttpReply::BadRequest); - reply.setPayload("400 Bad Request."); - writeData(socket, reply.data()); + HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); + reply->setClientId(clientId); + sendHttpReply(reply); + reply->deleteLater(); return; } - // verify HTTP version + // check HTTP version if (request.httpVersion() != "HTTP/1.1") { - qCWarning(dcWebServer) << "HTTP version is not supported." ; - HttpReply reply(HttpReply::HttpVersionNotSupported); - reply.setPayload("505 HTTP version is not supported."); - writeData(socket, reply.data()); + qCWarning(dcWebServer) << "HTTP version is not supported."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::HttpVersionNotSupported); + reply->setClientId(clientId); + sendHttpReply(reply); + reply->deleteLater(); return; } @@ -318,10 +323,11 @@ void WebServer::readClient() // verify method if (request.method() == HttpRequest::Unhandled) { - HttpReply reply(HttpReply::MethodNotAllowed); - reply.setHeader(HttpReply::AllowHeader, "GET, PUT, POST, DELETE, OPTIONS"); - reply.setPayload("405 Method not allowed."); - writeData(socket, reply.data()); + HttpReply *reply = RestResource::createErrorReply(HttpReply::MethodNotAllowed); + reply->setClientId(clientId); + reply->setHeader(HttpReply::AllowHeader, "GET, PUT, POST, DELETE, OPTIONS"); + sendHttpReply(reply); + reply->deleteLater(); return; } @@ -340,21 +346,24 @@ void WebServer::readClient() QFile file(path); if (file.open(QFile::ReadOnly | QFile::Truncate)) { qCDebug(dcWebServer) << "load file" << file.fileName(); - HttpReply reply(HttpReply::Ok); + HttpReply *reply = RestResource::createSuccessReply(); if (file.fileName().endsWith(".html")) { - reply.setHeader(HttpReply::ContentTypeHeader, "text/html; charset=\"utf-8\";"); + reply->setHeader(HttpReply::ContentTypeHeader, "text/html; charset=\"utf-8\";"); } - reply.setPayload(file.readAll()); - writeData(socket, reply.data()); + reply->setPayload(file.readAll()); + reply->setClientId(clientId); + sendHttpReply(reply); + reply->deleteLater(); return; } } // reject everything else... - qCWarning(dcWebServer) << "Unknown message received. Respond client with 400: Not Implemented."; - HttpReply reply(HttpReply::NotFound); - reply.setPayload("404 Not found."); - writeData(socket, reply.data()); + qCWarning(dcWebServer) << "Unknown message received. Respond client with 501: Not Implemented."; + HttpReply *reply = RestResource::createErrorReply(HttpReply::NotImplemented); + reply->setClientId(clientId); + sendHttpReply(reply); + reply->deleteLater(); } void WebServer::onDisconnected() diff --git a/server/webserver.h b/server/webserver.h index d17a29dd..560549ad 100644 --- a/server/webserver.h +++ b/server/webserver.h @@ -88,8 +88,6 @@ private: bool verifyFile(QSslSocket *socket, const QString &fileName); QString fileName(const QString &query); - void writeData(QSslSocket *socket, const QByteArray &data); - protected: void incomingConnection(qintptr socketDescriptor) override; diff --git a/tests/auto/restdevices/testrestdevices.cpp b/tests/auto/restdevices/testrestdevices.cpp index 80cac772..633b9d28 100644 --- a/tests/auto/restdevices/testrestdevices.cpp +++ b/tests/auto/restdevices/testrestdevices.cpp @@ -419,7 +419,7 @@ void TestRestDevices::editDevices() QNetworkRequest request(QUrl(QString("http://localhost:3333/api/v1/devices"))); - QNetworkReply *reply = nam->post(request, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); + QNetworkReply *reply = nam->post(request, QJsonDocument::fromVariant(params).toJson()); clientSpy.wait(); QCOMPARE(clientSpy.count(), 1); diff --git a/tests/auto/webserver/testwebserver.cpp b/tests/auto/webserver/testwebserver.cpp index 76f81561..d7d85132 100644 --- a/tests/auto/webserver/testwebserver.cpp +++ b/tests/auto/webserver/testwebserver.cpp @@ -142,11 +142,10 @@ void TestWebserver::multiPackageMessage() bool ok = false; int statusCode = firstLineTokens.at(1).toInt(&ok); QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 404); + QCOMPARE(statusCode, 501); socket->close(); socket->deleteLater(); - } void TestWebserver::checkAllowedMethodCall_data() @@ -205,7 +204,6 @@ void TestWebserver::checkAllowedMethodCall() printResponse(reply); QCOMPARE(clientSpy.count(), 1); - //QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); if (expectedStatusCode == 405){ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), expectedStatusCode);