fixed CORS and webserver and tests
This commit is contained in:
parent
653043f7b1
commit
ba5aedaaab
@ -79,7 +79,8 @@
|
||||
},
|
||||
{
|
||||
"name": "Google",
|
||||
"id": "d02399c5-8e79-4 0be-8cf6-e00b55bbfe7c",
|
||||
"idName": "google",
|
||||
"id": "d02399c5-8e79-40be-8cf6-e00b55bbfe7c",
|
||||
"deviceClasses": [
|
||||
{
|
||||
"deviceClassId": "3869884a-1592-4b8f-84a7-994be18ff555",
|
||||
@ -127,6 +128,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Yahoo",
|
||||
"idName": "yahoo",
|
||||
"id": "5eb3e1e9-25a7-4740-806e-5cfc836e4bf5",
|
||||
"deviceClasses": [
|
||||
{
|
||||
|
||||
@ -125,6 +125,7 @@ HttpReply::HttpReply(QObject *parent) :
|
||||
m_statusCode(HttpReply::Ok),
|
||||
m_type(HttpReply::TypeSync),
|
||||
m_payload(QByteArray()),
|
||||
m_closeConnection(false),
|
||||
m_timedOut(false)
|
||||
{
|
||||
m_timer = new QTimer(this);
|
||||
@ -252,6 +253,16 @@ QByteArray HttpReply::rawHeader() const
|
||||
return m_rawHeader;
|
||||
}
|
||||
|
||||
void HttpReply::setCloseConnection(const bool &close)
|
||||
{
|
||||
m_closeConnection = close;
|
||||
}
|
||||
|
||||
bool HttpReply::closeConnection() const
|
||||
{
|
||||
return m_closeConnection;
|
||||
}
|
||||
|
||||
/*! Returns true if the raw header and the payload of this \l{HttpReply} is empty.*/
|
||||
bool HttpReply::isEmpty() const
|
||||
{
|
||||
|
||||
@ -94,6 +94,9 @@ public:
|
||||
QHash<QByteArray, QByteArray> rawHeaderList() const;
|
||||
QByteArray rawHeader() const;
|
||||
|
||||
void setCloseConnection(const bool &close);
|
||||
bool closeConnection() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
void clear();
|
||||
|
||||
@ -115,6 +118,8 @@ private:
|
||||
|
||||
QHash<QByteArray, QByteArray> m_rawHeaderList;
|
||||
|
||||
bool m_closeConnection;
|
||||
|
||||
QTimer *m_timer;
|
||||
bool m_timedOut;
|
||||
|
||||
|
||||
@ -63,10 +63,10 @@ int main(int argc, char *argv[])
|
||||
s_loggingFilters.insert("RuleEngine", true);
|
||||
s_loggingFilters.insert("Connection", true);
|
||||
s_loggingFilters.insert("TcpServer", false);
|
||||
s_loggingFilters.insert("WebServer", false);
|
||||
s_loggingFilters.insert("WebServer", true);
|
||||
s_loggingFilters.insert("WebSocketServer", false);
|
||||
s_loggingFilters.insert("JsonRpc", false);
|
||||
s_loggingFilters.insert("Rest", false);
|
||||
s_loggingFilters.insert("Rest", true);
|
||||
s_loggingFilters.insert("Hardware", false);
|
||||
s_loggingFilters.insert("LogEngine", false);
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ HttpReply *DeviceClassesResource::proccessRequest(const HttpRequest &request, co
|
||||
}
|
||||
m_deviceClass = GuhCore::instance()->findDeviceClass(deviceClassId);
|
||||
if (!m_deviceClass.isValid()) {
|
||||
qCWarning(dcRest) << "DeviceClassId" << deviceClassId.toString() << "not found";
|
||||
return createErrorReply(HttpReply::NotFound);
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,9 +250,11 @@ HttpReply *DevicesResource::removeDevice(Device *device) const
|
||||
|
||||
// TODO: /api/v1/devices/{deviceId}?ruleId={ruleId}&removePolicy={RemovePolicy}
|
||||
|
||||
if (result == DeviceManager::DeviceErrorNoError)
|
||||
return createSuccessReply();
|
||||
|
||||
if (result == DeviceManager::DeviceErrorNoError) {
|
||||
HttpReply *reply = createSuccessReply();
|
||||
reply->setCloseConnection(true);
|
||||
return reply;
|
||||
}
|
||||
return createErrorReply(HttpReply::Forbidden);
|
||||
}
|
||||
|
||||
@ -322,7 +324,7 @@ HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const
|
||||
return createErrorReply(HttpReply::InternalServerError);
|
||||
|
||||
QVariantMap result;
|
||||
result.insert("deviceId", newDeviceId);
|
||||
result.insert("id", newDeviceId);
|
||||
HttpReply *reply = createSuccessReply();
|
||||
reply->setPayload(QJsonDocument::fromVariant(result).toJson());
|
||||
return reply;
|
||||
@ -458,7 +460,7 @@ void DevicesResource::deviceSetupFinished(Device *device, DeviceManager::DeviceE
|
||||
}
|
||||
|
||||
QVariantMap result;
|
||||
result.insert("deviceId", device->id());
|
||||
result.insert("id", device->id());
|
||||
reply->setPayload(QJsonDocument::fromVariant(result).toJson());
|
||||
reply->finished();
|
||||
}
|
||||
@ -489,7 +491,7 @@ void DevicesResource::pairingFinished(const PairingTransactionId &pairingTransac
|
||||
if (status == DeviceManager::DeviceErrorNoError) {
|
||||
qCDebug(dcRest) << "Pairing device finished successfully";
|
||||
QVariantMap response;
|
||||
response.insert("deviceId", deviceId.toString());
|
||||
response.insert("id", deviceId.toString());
|
||||
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
|
||||
reply->setHttpStatusCode(HttpReply::Ok);
|
||||
} else {
|
||||
|
||||
@ -111,6 +111,21 @@ void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &re
|
||||
return;
|
||||
}
|
||||
|
||||
// check CORS call
|
||||
if (request.method() == HttpRequest::Options) {
|
||||
HttpReply *reply = RestResource::createSuccessReply();
|
||||
reply->setHeader(HttpReply::ContentTypeHeader, "text/plain;");
|
||||
reply->setRawHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
|
||||
reply->setRawHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
||||
reply->setClientId(clientId);
|
||||
reply->setCloseConnection(true);
|
||||
m_webserver->sendHttpReply(reply);
|
||||
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// process request in corresponding resource
|
||||
RestResource *resource = m_resources.value(resourceName);
|
||||
HttpReply *reply = resource->proccessRequest(request, urlTokens);
|
||||
|
||||
@ -234,7 +234,7 @@ HttpReply *RulesResource::addRule(const QByteArray &payload) const
|
||||
|
||||
if (status == RuleEngine::RuleErrorNoError) {
|
||||
QVariantMap returns;
|
||||
returns.insert("ruleId", newRuleId.toString());
|
||||
returns.insert("id", newRuleId.toString());
|
||||
HttpReply *reply = createSuccessReply();
|
||||
reply->setPayload(QJsonDocument::fromVariant(returns).toJson());
|
||||
return reply;
|
||||
|
||||
@ -133,10 +133,12 @@ void WebServer::sendHttpReply(HttpReply *reply)
|
||||
QSslSocket *socket = 0;
|
||||
socket = m_clientList.value(reply->clientId());
|
||||
if (!socket) {
|
||||
qCDebug(dcWebServer) << "Invalid socket pointer! This should never happen!!!";
|
||||
qCDebug(dcWebServer) << "Invalid socket pointer! This should never happen!!! Missing clientId in reply?";
|
||||
return;
|
||||
}
|
||||
|
||||
writeData(socket, reply->data());
|
||||
socket->close();
|
||||
}
|
||||
|
||||
bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName)
|
||||
@ -190,7 +192,6 @@ QString WebServer::fileName(const QString &query)
|
||||
void WebServer::writeData(QSslSocket *socket, const QByteArray &data)
|
||||
{
|
||||
socket->write(data);
|
||||
//socket->close();
|
||||
}
|
||||
|
||||
void WebServer::incomingConnection(qintptr socketDescriptor)
|
||||
@ -291,13 +292,6 @@ void WebServer::readClient()
|
||||
return;
|
||||
}
|
||||
|
||||
// check CORS call
|
||||
if (request.method() == HttpRequest::Options) {
|
||||
HttpReply reply(HttpReply::Ok);
|
||||
reply.setRawHeader("Access-Control-Allow-Methods","PUT, POST, GET, DELETE, OPTIONS");
|
||||
writeData(socket, reply.data());
|
||||
}
|
||||
|
||||
// verify API query
|
||||
if (request.url().path().startsWith("/api/v1")) {
|
||||
emit httpRequestReady(clientId, request);
|
||||
|
||||
@ -93,8 +93,8 @@ void TestRestDeviceClasses::getSupportedDevices()
|
||||
QNetworkReply *reply = nam->get(request);
|
||||
clientSpy.wait();
|
||||
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||
// jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
// QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
jsonDoc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
reply->deleteLater();
|
||||
}
|
||||
nam->deleteLater();
|
||||
@ -276,8 +276,11 @@ void TestRestDeviceClasses::discoverDevices()
|
||||
QVariantList foundDevices = jsonDoc.toVariant().toList();
|
||||
QCOMPARE(foundDevices.count(), resultCount);
|
||||
|
||||
qDebug() << jsonDoc.toJson();
|
||||
|
||||
// ADD the discovered device
|
||||
request.setUrl(QUrl("http://localhost:3333/api/v1/devices"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
DeviceDescriptorId descriptorId = DeviceDescriptorId(foundDevices.first().toMap().value("id").toString());
|
||||
qDebug() << descriptorId;
|
||||
params.clear();
|
||||
@ -286,21 +289,25 @@ void TestRestDeviceClasses::discoverDevices()
|
||||
|
||||
clientSpy.clear();
|
||||
QByteArray payload = QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact);
|
||||
qDebug() << payload;
|
||||
reply = nam->post(request, payload);
|
||||
clientSpy.wait();
|
||||
QCOMPARE(clientSpy.count(), 1);
|
||||
data = reply->readAll();
|
||||
qDebug() << reply->rawHeaderList();
|
||||
qDebug() << data;
|
||||
|
||||
statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
reply->deleteLater();
|
||||
QCOMPARE(statusCode, expectedStatusCode);
|
||||
|
||||
// REMOVE added device
|
||||
jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||
|
||||
DeviceId deviceId = DeviceId(response.value("deviceId").toString());
|
||||
DeviceId deviceId = DeviceId(response.value("id").toString());
|
||||
QVERIFY2(!deviceId.isNull(), "got invalid device id");
|
||||
|
||||
// REMOVE added device
|
||||
|
||||
request = QNetworkRequest(QUrl(QString("http://localhost:3333/api/v1/devices/%1").arg(deviceId.toString())));
|
||||
clientSpy.clear();
|
||||
|
||||
@ -202,7 +202,8 @@ void TestRestDevices::addConfiguredDevice()
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||
|
||||
DeviceId deviceId = DeviceId(response.value("deviceId").toString());
|
||||
DeviceId deviceId = DeviceId(response.value("id").toString());
|
||||
QVERIFY2(!deviceId.isNull(),"invalid device id for removing");
|
||||
|
||||
request.setUrl(QUrl(QString("http://localhost:3333/api/v1/devices/%1").arg(deviceId.toString())));
|
||||
clientSpy.clear();
|
||||
@ -430,7 +431,7 @@ void TestRestDevices::editDevices()
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200);
|
||||
reply->deleteLater();
|
||||
QVariantMap responseMap = QJsonDocument::fromJson(data).toVariant().toMap();
|
||||
DeviceId deviceId = DeviceId(responseMap.value("deviceId").toString());
|
||||
DeviceId deviceId = DeviceId(responseMap.value("id").toString());
|
||||
qDebug() << deviceId.toString();
|
||||
QVERIFY2(deviceId != DeviceId(), "DeviceId not returned");
|
||||
|
||||
@ -561,7 +562,7 @@ void TestRestDevices::editByDiscovery()
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||
|
||||
DeviceId deviceId = DeviceId(response.value("deviceId").toString());
|
||||
DeviceId deviceId = DeviceId(response.value("id").toString());
|
||||
QVERIFY(!deviceId.isNull());
|
||||
|
||||
|
||||
@ -618,62 +619,6 @@ void TestRestDevices::editByDiscovery()
|
||||
QCOMPARE(statusCode, expectedStatusCode);
|
||||
reply->deleteLater();
|
||||
|
||||
|
||||
|
||||
// response = injectAndWait("Devices.EditDevice", params);
|
||||
// verifyDeviceError(response, error);
|
||||
|
||||
// response.clear();
|
||||
// response = injectAndWait("Devices.GetConfiguredDevices", QVariantMap());
|
||||
|
||||
// QVariantMap deviceMap;
|
||||
// bool found = false;
|
||||
// foreach (const QVariant device, response.toMap().value("params").toMap().value("devices").toList()) {
|
||||
// if (DeviceId(device.toMap().value("id").toString()) == deviceId) {
|
||||
// qDebug() << "found added device" << device.toMap().value("params");
|
||||
// found = true;
|
||||
// deviceMap = device.toMap();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// QVERIFY2(found, "Device missing in config!");
|
||||
// QCOMPARE(deviceMap.value("id").toString(), deviceId.toString());
|
||||
// if (deviceMap.contains("setupComplete")) {
|
||||
// QVERIFY2(deviceMap.value("setupComplete").toBool(), "Setup not completed after edit");
|
||||
// }
|
||||
|
||||
// // Note: this shows that by discovery a not editable param (name) can be changed!
|
||||
// foreach (QVariant param, deviceMap.value("params").toList()) {
|
||||
// if (param.toMap().value("name") == "name") {
|
||||
// QCOMPARE(param.toMap().value("value").toString(), QString("Discovered Mock Device 2"));
|
||||
// }
|
||||
// if (param.toMap().value("name") == "httpport") {
|
||||
// QCOMPARE(param.toMap().value("value").toInt(), 55556);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // check if the daemons are running
|
||||
// QNetworkAccessManager nam;
|
||||
// QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*)));
|
||||
|
||||
// // check if old daemon is still running (should not)
|
||||
// QNetworkRequest request(QUrl(QString("http://localhost:%1").arg(55555)));
|
||||
// QNetworkReply *reply = nam.get(request);
|
||||
// spy.wait();
|
||||
// QVERIFY2(reply->error(), "The old daemon is still running");
|
||||
// reply->deleteLater();
|
||||
|
||||
// // check if the daemon is realy running on the new port
|
||||
// request = QNetworkRequest(QUrl(QString("http://localhost:%1").arg(55556)));
|
||||
// reply = nam.get(request);
|
||||
// spy.wait();
|
||||
// QVERIFY2(reply->error() == QNetworkReply::NoError, "The new daemon is not running");
|
||||
// reply->deleteLater();
|
||||
|
||||
|
||||
|
||||
|
||||
// remove added device
|
||||
request = QNetworkRequest(QUrl(QString("http://localhost:3333/api/v1/devices/%1").arg(deviceId.toString())));
|
||||
clientSpy.clear();
|
||||
|
||||
@ -363,7 +363,7 @@ void TestRestRules::addRemoveRules()
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
reply->deleteLater();
|
||||
|
||||
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("ruleId").toString());
|
||||
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("id").toString());
|
||||
QVERIFY(!ruleId.isNull());
|
||||
|
||||
// GET rule details
|
||||
@ -677,7 +677,7 @@ void TestRestRules::editRules()
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
reply->deleteLater();
|
||||
|
||||
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("ruleId").toString());
|
||||
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("id").toString());
|
||||
QVERIFY(!ruleId.isNull());
|
||||
|
||||
// now create the new rule and edit the original one
|
||||
@ -792,7 +792,7 @@ void TestRestRules::enableDisableRule()
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
||||
|
||||
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("ruleId").toString());
|
||||
RuleId ruleId = RuleId(jsonDoc.toVariant().toMap().value("id").toString());
|
||||
QVERIFY(!ruleId.isNull());
|
||||
|
||||
// ENABLE rule
|
||||
|
||||
@ -176,6 +176,8 @@ void TestWebserver::checkAllowedMethodCall()
|
||||
request.setUrl(QUrl("http://localhost:3333"));
|
||||
QNetworkReply *reply = 0;
|
||||
|
||||
clientSpy.clear();
|
||||
|
||||
if (method == "GET") {
|
||||
reply = nam->get(request);
|
||||
} else if(method == "PUT") {
|
||||
@ -189,6 +191,7 @@ void TestWebserver::checkAllowedMethodCall()
|
||||
} else if(method == "CONNECT") {
|
||||
reply = nam->sendCustomRequest(request, "CONNECT");
|
||||
} else if(method == "OPTIONS") {
|
||||
request.setUrl(QUrl("http://localhost:3333/api/v1/devices"));
|
||||
reply = nam->sendCustomRequest(request, "OPTIONS");
|
||||
} else if(method == "TRACE") {
|
||||
reply = nam->sendCustomRequest(request, "TRACE");
|
||||
@ -197,8 +200,13 @@ void TestWebserver::checkAllowedMethodCall()
|
||||
reply = nam->get(request);
|
||||
}
|
||||
|
||||
clientSpy.wait(200);
|
||||
QVERIFY2(clientSpy.count() == 1, "expected exactly 1 response from webserver");
|
||||
clientSpy.wait();
|
||||
|
||||
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);
|
||||
QVERIFY2(reply->hasRawHeader("Allow"), "405 should contain the allowed methods header");
|
||||
@ -229,7 +237,6 @@ void TestWebserver::badRequests_data()
|
||||
userAgentMissing.append("GET / HTTP/1.1\r\n");
|
||||
userAgentMissing.append("\r\n");
|
||||
|
||||
|
||||
QTest::newRow("wrong content length") << wrongContentLength << 400;
|
||||
QTest::newRow("invalid header formatting") << wrongHeaderFormatting << 400;
|
||||
QTest::newRow("user agent missing") << userAgentMissing << 400;
|
||||
|
||||
Reference in New Issue
Block a user