diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 84749bd975..b6a52358e5 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -317,6 +317,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url #endif bool showStats = false; + QString persistFile = "/" + getPersistFilename(); if (connection->requestOperation() == QNetworkAccessManager::GetOperation) { if (url.path() == "/") { @@ -326,6 +327,18 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url _tree->resetEditStats(); resetSendingStats(); showStats = true; + } else if ((url.path() == persistFile) || (url.path() == persistFile + "/")) { + if (_persistFileDownload) { + QByteArray persistFileContents = getPersistFileContents(); + if (persistFileContents.length() > 0) { + connection->respond(HTTPConnection::StatusCode200, persistFileContents, qPrintable(getPersistFileMimeType())); + } else { + connection->respond(HTTPConnection::StatusCode500, HTTPConnection::StatusCode500); + } + } else { + connection->respond(HTTPConnection::StatusCode403, HTTPConnection::StatusCode403); // not allowed + } + return true; } } @@ -367,6 +380,12 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url statsString += getFileLoadTime(); statsString += "\r\n"; + if (_persistFileDownload) { + statsString += QString("Persist file: %1\r\n").arg(persistFile); + } else { + statsString += QString("Persist file: %1\r\n").arg(persistFile); + } + } else { statsString += "Octree file not yet loaded...\r\n"; } @@ -1026,7 +1045,8 @@ bool OctreeServer::readConfiguration() { _wantBackup = !noBackup; qDebug() << "wantBackup=" << _wantBackup; - //qDebug() << "settingsSectionObject:" << settingsSectionObject; + readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload); + qDebug() << "persistFileDownload=" << _persistFileDownload; } else { qDebug("persistFilename= DISABLED"); diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index b8e4a5c261..6d4eb89f66 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -59,6 +59,9 @@ public: bool isInitialLoadComplete() const { return (_persistThread) ? _persistThread->isInitialLoadComplete() : true; } bool isPersistEnabled() const { return (_persistThread) ? true : false; } quint64 getLoadElapsedTime() const { return (_persistThread) ? _persistThread->getLoadElapsedTime() : 0; } + QString getPersistFilename() const { return (_persistThread) ? _persistThread->getPersistFilename() : ""; } + QString getPersistFileMimeType() const { return (_persistThread) ? _persistThread->getPersistFileMimeType() : "text/plain"; } + QByteArray getPersistFileContents() const { return (_persistThread) ? _persistThread->getPersistFileContents() : QByteArray(); } // Subclasses must implement these methods virtual OctreeQueryNode* createOctreeQueryNode() = 0; @@ -173,6 +176,7 @@ protected: int _persistInterval; bool _wantBackup; + bool _persistFileDownload; QString _backupExtensionFormat; int _backupInterval; int _maxBackupVersions; diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index e0038117f0..2332f25dfa 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -476,6 +476,14 @@ "default": "", "advanced": true }, + { + "name": "persistFileDownload", + "type": "checkbox", + "label": "Persist File Download", + "help": "Includes a download link to the persist file in the server status page.", + "default": false, + "advanced": true + }, { "name": "wantEditLogging", "type": "checkbox", diff --git a/libraries/embedded-webserver/src/HTTPConnection.cpp b/libraries/embedded-webserver/src/HTTPConnection.cpp index fb69499059..b0cd55c085 100644 --- a/libraries/embedded-webserver/src/HTTPConnection.cpp +++ b/libraries/embedded-webserver/src/HTTPConnection.cpp @@ -23,7 +23,9 @@ const char* HTTPConnection::StatusCode301 = "301 Moved Permanently"; const char* HTTPConnection::StatusCode302 = "302 Found"; const char* HTTPConnection::StatusCode400 = "400 Bad Request"; const char* HTTPConnection::StatusCode401 = "401 Unauthorized"; +const char* HTTPConnection::StatusCode403 = "403 Forbidden"; const char* HTTPConnection::StatusCode404 = "404 Not Found"; +const char* HTTPConnection::StatusCode500 = "500 Internal server error"; const char* HTTPConnection::DefaultContentType = "text/plain; charset=ISO-8859-1"; HTTPConnection::HTTPConnection (QTcpSocket* socket, HTTPManager* parentManager) : diff --git a/libraries/embedded-webserver/src/HTTPConnection.h b/libraries/embedded-webserver/src/HTTPConnection.h index c981537c15..23a4db5bc2 100644 --- a/libraries/embedded-webserver/src/HTTPConnection.h +++ b/libraries/embedded-webserver/src/HTTPConnection.h @@ -47,7 +47,9 @@ public: static const char* StatusCode302; static const char* StatusCode400; static const char* StatusCode401; + static const char* StatusCode403; static const char* StatusCode404; + static const char* StatusCode500; static const char* DefaultContentType; /// WebSocket close status codes. diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 5cbb30ef49..03794e2223 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -52,6 +52,15 @@ OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& file _filename = sansExt + "." + _persistAsFileType; } +QString OctreePersistThread::getPersistFileMimeType() const { + if (_persistAsFileType == "json") { + return "application/json"; + } if (_persistAsFileType == "json.gz") { + return "application/zip"; + } + return ""; +} + void OctreePersistThread::parseSettings(const QJsonObject& settings) { if (settings["backups"].isArray()) { const QJsonArray& backupRules = settings["backups"].toArray(); @@ -229,6 +238,15 @@ void OctreePersistThread::aboutToFinish() { _stopThread = true; } +QByteArray OctreePersistThread::getPersistFileContents() const { + QByteArray fileContents; + QFile file(_filename); + if (file.open(QIODevice::ReadOnly)) { + fileContents = file.readAll(); + } + return fileContents; +} + void OctreePersistThread::persist() { if (_tree->isDirty()) { diff --git a/libraries/octree/src/OctreePersistThread.h b/libraries/octree/src/OctreePersistThread.h index d3aa3d3968..061a7a0e15 100644 --- a/libraries/octree/src/OctreePersistThread.h +++ b/libraries/octree/src/OctreePersistThread.h @@ -42,6 +42,10 @@ public: void aboutToFinish(); /// call this to inform the persist thread that the owner is about to finish to support final persist + QString getPersistFilename() const { return _filename; } + QString getPersistFileMimeType() const; + QByteArray getPersistFileContents() const; + signals: void loadCompleted();