fix tests and http reply

This commit is contained in:
Simon Stürz 2015-09-05 15:11:08 +02:00 committed by Michael Zanetti
parent fad59b5411
commit b11206cbc8
10 changed files with 58 additions and 46 deletions

View File

@ -170,6 +170,7 @@ HttpReply::HttpReply(const HttpReply::HttpStatusCode &statusCode, const HttpRepl
void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode) void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode)
{ {
m_statusCode = statusCode; m_statusCode = statusCode;
m_reasonPhrase = getHttpReasonPhrase(m_statusCode);
packReply(); packReply();
} }

View File

@ -101,7 +101,6 @@ HttpReply *DevicesResource::proccessGetRequest(const HttpRequest &request, const
if (urlTokens.count() == 5 && urlTokens.at(4) == "states") if (urlTokens.count() == 5 && urlTokens.at(4) == "states")
return getDeviceStateValues(m_device); return getDeviceStateValues(m_device);
// /api/v1/devices/{deviceId}/states/{stateTypeId} // /api/v1/devices/{deviceId}/states/{stateTypeId}
if (urlTokens.count() >= 6 && urlTokens.at(4) == "states") { if (urlTokens.count() >= 6 && urlTokens.at(4) == "states") {
StateTypeId stateTypeId = StateTypeId(urlTokens.at(5)); StateTypeId stateTypeId = StateTypeId(urlTokens.at(5));
@ -152,7 +151,6 @@ HttpReply *DevicesResource::proccessPutRequest(const HttpRequest &request, const
HttpReply *DevicesResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) HttpReply *DevicesResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
{ {
// POST /api/v1/devices // POST /api/v1/devices
if (urlTokens.count() == 3) if (urlTokens.count() == 3)
return addConfiguredDevice(request.payload()); return addConfiguredDevice(request.payload());
@ -199,7 +197,6 @@ HttpReply *DevicesResource::proccessOptionsRequest(const HttpRequest &request, c
{ {
Q_UNUSED(request) Q_UNUSED(request)
Q_UNUSED(urlTokens) Q_UNUSED(urlTokens)
qCDebug(dcRest) << "process options request\n" << request;
return RestResource::createCorsSuccessReply(); return RestResource::createCorsSuccessReply();
} }
@ -263,7 +260,6 @@ HttpReply *DevicesResource::removeDevice(Device *device) const
if (result == DeviceManager::DeviceErrorNoError) { if (result == DeviceManager::DeviceErrorNoError) {
HttpReply *reply = createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setCloseConnection(true);
return reply; return reply;
} }
return createErrorReply(HttpReply::Forbidden); return createErrorReply(HttpReply::Forbidden);

View File

@ -82,6 +82,7 @@ RestResource::~RestResource()
HttpReply *RestResource::createSuccessReply() HttpReply *RestResource::createSuccessReply()
{ {
HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeSync); HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeSync);
reply->setPayload("200 Ok");
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
return reply; return reply;
} }
@ -90,12 +91,12 @@ HttpReply *RestResource::createCorsSuccessReply()
{ {
HttpReply *reply = RestResource::createSuccessReply(); HttpReply *reply = RestResource::createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain");
reply->setRawHeader("Accept","text/plain"); reply->setRawHeader("Accept","application/json");
reply->setRawHeader("Allow", "PUT, POST, GET, DELETE, OPTIONS"); reply->setRawHeader("Allow", "PUT, POST, GET, DELETE, OPTIONS");
reply->setRawHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS"); reply->setRawHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
reply->setHeader(HttpReply::ContentLenghtHeader, QByteArray::number(0));
reply->setRawHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept"); reply->setRawHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept");
reply->setRawHeader("Access-Control-Max-Age", "1728000"); reply->setRawHeader("Access-Control-Max-Age", "1728000");
//reply->setCloseConnection(true);
return reply; return reply;
} }
@ -111,6 +112,7 @@ HttpReply *RestResource::createErrorReply(const HttpReply::HttpStatusCode &statu
HttpReply *RestResource::createAsyncReply() HttpReply *RestResource::createAsyncReply()
{ {
HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeAsync); HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeAsync);
reply->setPayload(QByteArray::number(reply->httpStatusCode()) + " " + reply->httpReasonPhrase());
return reply; return reply;
} }

View File

@ -113,10 +113,8 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re
// check CORS call for main resource // check CORS call for main resource
if (request.method() == HttpRequest::Options && urlTokens.count() == 3) { if (request.method() == HttpRequest::Options && urlTokens.count() == 3) {
qCDebug(dcRest) << "process options request\n" << request;
HttpReply *reply = RestResource::createCorsSuccessReply(); HttpReply *reply = RestResource::createCorsSuccessReply();
reply->setClientId(clientId); reply->setClientId(clientId);
qCDebug(dcRest) << reply->data();
m_webserver->sendHttpReply(reply); m_webserver->sendHttpReply(reply);
reply->deleteLater(); reply->deleteLater();
return; return;

View File

@ -182,9 +182,11 @@ HttpReply *RulesResource::removeRule(const RuleId &ruleId) const
RuleEngine::RuleError status = GuhCore::instance()->removeRule(ruleId); RuleEngine::RuleError status = GuhCore::instance()->removeRule(ruleId);
if (status == RuleEngine::RuleErrorNoError) if (status == RuleEngine::RuleErrorNoError) {
return createSuccessReply(); HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentLenghtHeader, "0");
return reply;
}
return createErrorReply(HttpReply::InternalServerError); return createErrorReply(HttpReply::InternalServerError);
} }

View File

@ -1,3 +1,4 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> * * Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
@ -141,11 +142,12 @@ void WebServer::sendHttpReply(HttpReply *reply)
// send raw data // send raw data
reply->packReply(); reply->packReply();
qCDebug(dcWebServer) << "respond" << reply->httpStatusCode() << reply->httpReasonPhrase();
socket->write(reply->data()); socket->write(reply->data());
// close the connection if wanted // // close the connection if wanted
if (reply->closeConnection()) // if (reply->closeConnection())
socket->close(); // socket->close();
} }
@ -255,7 +257,6 @@ void WebServer::incomingConnection(qintptr socketDescriptor)
emit clientConnected(clientId); emit clientConnected(clientId);
} }
void WebServer::readClient() void WebServer::readClient()
{ {
if (!m_enabled) if (!m_enabled)
@ -268,7 +269,6 @@ void WebServer::readClient()
if (clientId.isNull()) { if (clientId.isNull()) {
qCWarning(dcWebServer) << "Client not recognized"; qCWarning(dcWebServer) << "Client not recognized";
socket->close(); socket->close();
socket->deleteLater();
return; return;
} }
@ -350,6 +350,9 @@ void WebServer::readClient()
if (file.fileName().endsWith(".html")) { if (file.fileName().endsWith(".html")) {
reply->setHeader(HttpReply::ContentTypeHeader, "text/html; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "text/html; charset=\"utf-8\";");
} }
if (file.fileName().endsWith(".css")) {
reply->setHeader(HttpReply::ContentTypeHeader, "text/css; charset=\"utf-8\";");
}
reply->setPayload(file.readAll()); reply->setPayload(file.readAll());
reply->setClientId(clientId); reply->setClientId(clientId);
sendHttpReply(reply); sendHttpReply(reply);
@ -369,15 +372,30 @@ void WebServer::readClient()
void WebServer::onDisconnected() void WebServer::onDisconnected()
{ {
QSslSocket* socket = static_cast<QSslSocket *>(sender()); QSslSocket* socket = static_cast<QSslSocket *>(sender());
qCDebug(dcConnection) << "Webserver client disonnected.";
// remove connection from server client
foreach (WebServerClient *client, m_webServerClients) {
if (client->address() == socket->peerAddress()) {
client->removeConnection(socket);
qCDebug(dcWebServer) << "connection count" << client->connections().count();
if (client->connections().isEmpty()) {
m_webServerClients.removeAll(client);
qCDebug(dcWebServer) << "delete client" << client->address().toString();
client->deleteLater();
}
break;
}
}
qCDebug(dcConnection) << 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);
m_clientList.remove(clientId); m_clientList.remove(clientId);
m_incompleteRequests.remove(socket); m_incompleteRequests.remove(socket);
socket->deleteLater();
emit clientDisconnected(clientId); emit clientDisconnected(clientId);
socket->deleteLater();
} }
void WebServer::onEncrypted() void WebServer::onEncrypted()
@ -405,6 +423,7 @@ bool WebServer::startServer()
m_enabled = false; m_enabled = false;
return false; return false;
} }
if (m_useSsl) { if (m_useSsl) {
qCDebug(dcConnection) << "Started webserver on" << QString("https://%1:%2").arg(serverAddress().toString()).arg(m_port); qCDebug(dcConnection) << "Started webserver on" << QString("https://%1:%2").arg(serverAddress().toString()).arg(m_port);
} else { } else {
@ -444,17 +463,24 @@ void WebServerClient::addConnection(QSslSocket *socket)
{ {
QTimer *timer = new QTimer(this); QTimer *timer = new QTimer(this);
timer->setSingleShot(true); timer->setSingleShot(true);
timer->setInterval(6000); timer->setInterval(9500);
connect(timer, &QTimer::timeout, this, &WebServerClient::onTimout); connect(timer, &QTimer::timeout, this, &WebServerClient::onTimout);
m_runningConnections.insert(timer, socket); m_runningConnections.insert(timer, socket);
m_connections.append(socket); m_connections.append(socket);
connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
timer->start(); timer->start();
} }
void WebServerClient::removeConnection(QSslSocket *socket)
{
QTimer *timer = m_runningConnections.key(socket);
m_runningConnections.remove(timer);
m_connections.removeAll(socket);
timer->deleteLater();
}
void WebServerClient::resetTimout(QSslSocket *socket) void WebServerClient::resetTimout(QSslSocket *socket)
{ {
QTimer *timer = 0; QTimer *timer = 0;
@ -466,22 +492,10 @@ void WebServerClient::resetTimout(QSslSocket *socket)
void WebServerClient::onTimout() void WebServerClient::onTimout()
{ {
QTimer *timer = static_cast<QTimer *>(sender()); QTimer *timer = static_cast<QTimer *>(sender());
QSslSocket *socket = m_runningConnections.take(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) << QString("Client connection timout %1:%2 -> closing connection").arg(socket->peerAddress().toString()).arg(socket->peerPort());
socket->close(); socket->close();
timer->deleteLater();
} }
void WebServerClient::onDisconnected()
{
QSslSocket *socket = static_cast<QSslSocket *>(sender());
if (!m_runningConnections.values().contains(socket))
return;
QTimer *timer = m_runningConnections.key(socket);
m_runningConnections.remove(timer);
timer->deleteLater();
}
} }

View File

@ -50,6 +50,7 @@ public:
QList<QSslSocket *> connections(); QList<QSslSocket *> connections();
void addConnection(QSslSocket *socket); void addConnection(QSslSocket *socket);
void removeConnection(QSslSocket *socket);
void resetTimout(QSslSocket *socket); void resetTimout(QSslSocket *socket);
@ -60,7 +61,7 @@ private:
private slots: private slots:
void onTimout(); void onTimout();
void onDisconnected();
}; };

View File

@ -297,19 +297,19 @@ void TestRestDeviceClasses::discoverDevices()
qDebug() << data; qDebug() << data;
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
reply->deleteLater();
QCOMPARE(statusCode, expectedStatusCode); QCOMPARE(statusCode, expectedStatusCode);
jsonDoc = QJsonDocument::fromJson(data, &error); jsonDoc = QJsonDocument::fromJson(data, &error);
QCOMPARE(error.error, QJsonParseError::NoError); QCOMPARE(error.error, QJsonParseError::NoError);
reply->deleteLater();
QVariantMap response = jsonDoc.toVariant().toMap(); QVariantMap response = jsonDoc.toVariant().toMap();
DeviceId deviceId = DeviceId(response.value("id").toString()); DeviceId deviceId = DeviceId(response.value("id").toString());
QVERIFY2(!deviceId.isNull(), "got invalid device id"); QVERIFY2(!deviceId.isNull(), "got invalid device id");
// REMOVE added device // REMOVE added device
request = QNetworkRequest(QUrl(QString("http://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); request = QNetworkRequest(QUrl(QString("http://localhost:3333/api/v1/devices/%1").arg(deviceId.toString())));
qDebug() << request.url().toString();
clientSpy.clear(); clientSpy.clear();
reply = nam->deleteResource(request); reply = nam->deleteResource(request);
clientSpy.wait(); clientSpy.wait();

View File

@ -419,7 +419,7 @@ void TestRestDevices::editDevices()
QNetworkRequest request(QUrl(QString("http://localhost:3333/api/v1/devices"))); QNetworkRequest request(QUrl(QString("http://localhost:3333/api/v1/devices")));
QNetworkReply *reply = nam->post(request, QJsonDocument::fromVariant(params).toJson()); QNetworkReply *reply = nam->post(request, QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact));
clientSpy.wait(); clientSpy.wait();
QCOMPARE(clientSpy.count(), 1); QCOMPARE(clientSpy.count(), 1);

View File

@ -160,7 +160,7 @@ void TestRestDeviceClasses::setPluginConfiguration()
request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString())));
QNetworkReply *reply = nam->get(request); QNetworkReply *reply = nam->get(request);
clientSpy.wait(); clientSpy.wait();
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); QCOMPARE(clientSpy.count(), 1);
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
reply->deleteLater(); reply->deleteLater();
@ -184,7 +184,7 @@ void TestRestDeviceClasses::setPluginConfiguration()
request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString())));
reply = nam->put(request, QJsonDocument::fromVariant(newConfigurations).toJson(QJsonDocument::Compact)); reply = nam->put(request, QJsonDocument::fromVariant(newConfigurations).toJson(QJsonDocument::Compact));
clientSpy.wait(); clientSpy.wait();
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); QCOMPARE(clientSpy.count(), 1);
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QCOMPARE(statusCode, expectedStatusCode); QCOMPARE(statusCode, expectedStatusCode);
reply->deleteLater(); reply->deleteLater();
@ -197,7 +197,7 @@ void TestRestDeviceClasses::setPluginConfiguration()
request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString())));
reply = nam->get(request); reply = nam->get(request);
clientSpy.wait(); clientSpy.wait();
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); QCOMPARE(clientSpy.count(), 1);
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QCOMPARE(statusCode, expectedStatusCode); QCOMPARE(statusCode, expectedStatusCode);
data = reply->readAll(); data = reply->readAll();
@ -211,14 +211,12 @@ void TestRestDeviceClasses::setPluginConfiguration()
// verify new configurations // verify new configurations
verifyParams(newConfigurations, checkConfigurations); verifyParams(newConfigurations, checkConfigurations);
restartServer();
// check new configurations after restart // check new configurations after restart
clientSpy.clear(); clientSpy.clear();
request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); request.setUrl(QUrl(QString("http://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString())));
reply = nam->get(request); reply = nam->get(request);
clientSpy.wait(); clientSpy.wait();
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver"); QCOMPARE(clientSpy.count(), 1);
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QCOMPARE(statusCode, 200); QCOMPARE(statusCode, 200);
data = reply->readAll(); data = reply->readAll();