diff --git a/Modules/CppRestSdk/include/mitkRESTManager.h b/Modules/CppRestSdk/include/mitkRESTManager.h index a7df8f23b8..25bd58e765 100644 --- a/Modules/CppRestSdk/include/mitkRESTManager.h +++ b/Modules/CppRestSdk/include/mitkRESTManager.h @@ -1,121 +1,120 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRESTManager_h #define mitkRESTManager_h #include #include namespace mitk { /** * @class RESTManager * @brief this is a microservice for managing REST-requests, used for non-qt applications. * * RESTManagerQt in the CppRestSdkQt module inherits from this class and is the equivalent microservice * used for Qt applications. */ class MITKCPPRESTSDK_EXPORT RESTManager : public IRESTManager { public: RESTManager(); ~RESTManager() override; /** * @brief Executes a HTTP request in the mitkRESTClient class * * @throw mitk::Exception if RequestType is not suported * @param uri defines the URI the request is send to * @param type the RequestType of the HTTP request (optional) * @param body the body for the request (optional) * @param filePath the file path to store the request to * @return task to wait for */ pplx::task SendRequest(const web::uri &uri, const RequestType &type = RequestType::Get, const web::json::value *body = nullptr, const utility::string_t &filePath = {}) override; /** * @brief starts listening for requests if there isn't another observer listening and the port is free * * @param uri defines the URI for which incoming requests should be send to the observer * @param observer the observer which handles the incoming requests */ void ReceiveRequest(const web::uri &uri, IRESTObserver *observer) override; /** * @brief Handles incoming requests by notifying the observer which should receive it * * @param uri defines the URI of the request * @param body the body of the request * @return the data which is modified by the notified observer */ web::json::value Handle(const web::uri &uri, const web::json::value &body) override; /** * @brief Handles the deletion of an observer for all or a specific uri * * @param observer the observer which shouldn't receive requests anymore * @param uri the uri for which the observer doesn't handle requests anymore (optional) */ virtual void HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri = {}) override; /** * @brief internal use only */ virtual const std::map& GetServerMap() override; virtual std::map, IRESTObserver *>& GetObservers() override; protected: /** * @brief adds an observer if a port is free, called by ReceiveRequest method * * @param uri the uri which builds the key for the observer map * @param observer the observer which is added */ void AddObserver(const web::uri &uri, IRESTObserver *observer); /** * @brief handles server management if there is already a server under a port, called by ReceiveRequest method * * @param uri the uri which which is requested to be added * @param observer the observer which proceeds the request */ void RequestForATakenPort(const web::uri &uri, IRESTObserver *observer); /** * @brief deletes an observer, called by HandleDeleteObserver method * * @param it the iterator comparing the observers in HandleDeleteObserver method - * @param the uri for which the observer doesn't want to receive requests anymore * @return bool if there is another observer under the port */ - bool DeleteObserver(std::map, IRESTObserver *>::iterator &it, const web::uri &uri); + bool DeleteObserver(std::map, IRESTObserver *>::iterator &it); void SetServerMap(const int port, RESTServer *server); void DeleteFromServerMap(const int port); void SetObservers(const std::pair key, IRESTObserver *observer); private: std::map m_ServerMap; // Map with port server pairs std::map, IRESTObserver *> m_Observers; // Map with all observers }; } // namespace mitk #endif // !mitkRESTManager_h diff --git a/Modules/CppRestSdk/src/mitkRESTManager.cpp b/Modules/CppRestSdk/src/mitkRESTManager.cpp index aee08ac086..f77373c18c 100644 --- a/Modules/CppRestSdk/src/mitkRESTManager.cpp +++ b/Modules/CppRestSdk/src/mitkRESTManager.cpp @@ -1,218 +1,213 @@ #include "mitkRESTManager.h" #include #include mitk::RESTManager::RESTManager() {} mitk::RESTManager::~RESTManager() {} pplx::task mitk::RESTManager::SendRequest(const web::uri &uri, const RequestType &type, const web::json::value *content, const utility::string_t &filePath) { pplx::task answer; auto client = new RESTClient(); // according to the RequestType, different HTTP requests are made switch (type) { case RequestType::Get: if (filePath.empty()) { // no file path specified, starts a normal get request returning the normal json result answer = client->Get(uri); } else { // file path ist specified, the result of the get request ist stored in this file // and an empty json object is returned answer = client->Get(uri, filePath); } break; case RequestType::Post: if (nullptr == content) { // warning because normally you won't create an empty ressource MITK_WARN << "Content for put is empty, this will create an empty ressource"; } answer = client->Post(uri, content); break; case RequestType::Put: if (nullptr == content) { // warning because normally you won't empty a ressource MITK_WARN << "Content for put is empty, this will empty the ressource"; } answer = client->Put(uri, content); break; default: mitkThrow() << "Request Type not supported"; break; } return answer; } void mitk::RESTManager::ReceiveRequest(const web::uri &uri, mitk::IRESTObserver *observer) { // New instance of RESTServer in m_ServerMap, key is port of the request int port = uri.port(); // Checking if port is free to add a new Server if (0 == m_ServerMap.count(port)) { this->AddObserver(uri, observer); // creating server instance auto server = new RESTServer(uri.authority()); // add reference to server instance to map m_ServerMap[port] = server; // start Server server->OpenListener(); MITK_INFO << "new server " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()) << " at port " << port; } // If there is already a server under this port else { this->RequestForATakenPort(uri, observer); } } web::json::value mitk::RESTManager::Handle(const web::uri &uri, const web::json::value &body) { // Checking if there is an observer for the port and path std::pair key(uri.port(), uri.path()); if (0 != m_Observers.count(key)) { return m_Observers[key]->Notify(uri, body); } // No observer under this port, return null which results in status code 404 (s. RESTServer) else { MITK_WARN << "No Observer can handle the data"; return web::json::value(); } } void mitk::RESTManager::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) { for (auto it = m_Observers.begin(); it != m_Observers.end();) { mitk::IRESTObserver *obsMap = it->second; // Check wether observer is at this place in map if (observer == obsMap) { // Check wether it is the right uri to be deleted if (uri.is_empty() || uri.path() == it->first.second) { int port = it->first.first; - bool noObserverForPort = this->DeleteObserver(it, uri); + bool noObserverForPort = this->DeleteObserver(it); if (noObserverForPort) { // there isn't an observer at this port, delete m_ServerMap entry for this port // close listener m_ServerMap[port]->CloseListener(); delete m_ServerMap[port]; // delete server from map m_ServerMap.erase(port); } } else { ++it; } } else { ++it; } } } const std::map &mitk::RESTManager::GetServerMap() { return m_ServerMap; } std::map, mitk::IRESTObserver *> &mitk::RESTManager::GetObservers() { return m_Observers; } void mitk::RESTManager::AddObserver(const web::uri &uri, IRESTObserver *observer) { // new observer has to be added std::pair key(uri.port(), uri.path()); m_Observers[key] = observer; } void mitk::RESTManager::RequestForATakenPort(const web::uri &uri, IRESTObserver *observer) { // Same host, means new observer but not a new server instance if (uri.authority() == m_ServerMap[uri.port()]->GetUri()) { // new observer has to be added std::pair key(uri.port(), uri.path()); // only add a new observer if there isn't already an observer for this uri if (0 == m_Observers.count(key)) { this->AddObserver(uri, observer); // info output MITK_INFO << "started listening, no new server instance has been created"; } else { MITK_ERROR << "Threre is already a observer handeling this data"; } } // Error, since another server can't be added under this port else { MITK_ERROR << "There is already another server listening under this port"; } } -bool mitk::RESTManager::DeleteObserver(std::map, IRESTObserver *>::iterator &it, - const web::uri &uri) +bool mitk::RESTManager::DeleteObserver(std::map, IRESTObserver *>::iterator &it) { - // if yes - // 1. store port and path in a temporary variable - // (path is only needed to create a key for info output) int port = it->first.first; - utility::string_t path = it->first.second; - std::pair key(port, path); - // 2. delete map entry + it = m_Observers.erase(it); - // 3. check, if there is another observer under this port in observer map (with bool flag) - for (auto o : m_Observers) + + for (auto observer : m_Observers) { - if (port == o.first.first) + if (port == observer.first.first) { // there still exists an observer for this port return false; } } + return true; } void mitk::RESTManager::SetServerMap(const int port, RESTServer *server) { m_ServerMap[port] = server; } void mitk::RESTManager::DeleteFromServerMap(const int port) { m_ServerMap.erase(port); } void mitk::RESTManager::SetObservers(const std::pair key, IRESTObserver *observer) { m_Observers[key] = observer; } diff --git a/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp b/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp index 0d5f84ca5d..dbe2c9b5fd 100644 --- a/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp +++ b/Modules/CppRestSdkQt/src/mitkRESTManagerQt.cpp @@ -1,80 +1,80 @@ #include "mitkRESTManagerQt.h" #include #include mitk::RESTManagerQt::RESTManagerQt() {} mitk::RESTManagerQt::~RESTManagerQt() {} void mitk::RESTManagerQt::ReceiveRequest(const web::uri &uri, mitk::IRESTObserver *observer) { // New instance of RESTServer in m_ServerMap, key is port of the request int port = uri.port(); // Checking if port is free to add a new Server if (0 == GetServerMap().count(port)) { mitk::RESTManager::AddObserver(uri, observer); // creating server instance auto server = new RESTServerQt(uri.authority()); // add reference to server instance to map mitk::RESTManager::SetServerMap(port, server); // Move server to seperate Thread and create connections between threads m_ServerThreadMap[port] = new QThread; server->moveToThread(m_ServerThreadMap[port]); connect(m_ServerThreadMap[port], &QThread::finished, server, &QObject::deleteLater); // starting Server m_ServerThreadMap[port]->start(); QMetaObject::invokeMethod(server, "OpenListener"); MITK_INFO << "new server " << mitk::RESTUtil::convertToUtf8(uri.authority().to_string()) << " at port " << port; } // If there is already a server under this port else { mitk::RESTManager::RequestForATakenPort(uri, observer); } } void mitk::RESTManagerQt::HandleDeleteObserver(IRESTObserver *observer, const web::uri &uri) { auto &observerMap = mitk::RESTManager::GetObservers(); for (auto it = observerMap.begin(); it != observerMap.end();) { mitk::IRESTObserver *obsMap = it->second; // Check wether observer is at this place in map if (observer == obsMap) { // Check wether it is the right uri to be deleted if (uri.is_empty() || uri.path() == it->first.second) { int port = it->first.first; - bool noObserverForPort = mitk::RESTManager::DeleteObserver(it, uri); + bool noObserverForPort = mitk::RESTManager::DeleteObserver(it); if (noObserverForPort) { // there isn't an observer at this port, delete m_ServerMap entry for this port // close listener QMetaObject::invokeMethod(static_cast(mitk::RESTManager::GetServerMap().at(port)), "CloseListener"); // end thread m_ServerThreadMap[port]->quit(); m_ServerThreadMap[port]->wait(); // delete server from map mitk::RESTManager::DeleteFromServerMap(port); } } else { ++it; } } else { ++it; } } }