fix replies from webserver

This commit is contained in:
Simon Stürz 2015-08-28 14:44:34 +02:00 committed by Michael Zanetti
parent d759602915
commit 01f9b418a9
7 changed files with 62 additions and 49 deletions

View File

@ -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();

View File

@ -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;
}

View File

@ -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();

View File

@ -75,6 +75,7 @@
#include "guhsettings.h"
#include "httpreply.h"
#include "httprequest.h"
#include "rest/restresource.h"
#include <QJsonDocument>
#include <QTcpServer>
@ -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()

View File

@ -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;

View File

@ -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);

View File

@ -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);