diff --git a/Modules/REST/include/mitkRESTClient.h b/Modules/REST/include/mitkRESTClient.h index fc3c2dac42..c877503058 100644 --- a/Modules/REST/include/mitkRESTClient.h +++ b/Modules/REST/include/mitkRESTClient.h @@ -1,106 +1,108 @@ /*=================================================================== 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 mitkRESTClient_h #define mitkRESTClient_h #include #include namespace mitk { class MITKREST_EXPORT RESTClient { public: using http_request = web::http::http_request; RESTClient(); ~RESTClient(); /** * @brief Executes a HTTP GET request with the given uri and returns a task waiting for a json object * * @throw mitk::Exception if request went wrong * @param uri the URI resulting the target of the HTTP request * @param the additional headers to be set to the HTTP request * @return task to wait for with resulting json object */ pplx::task Get(const web::uri &uri, const std::map headers); /** * @brief Executes a HTTP GET request with the given uri and and stores the byte stream in a file given by the * filePath * * @throw mitk::Exception if request went wrong * @param uri the URI resulting the target of the HTTP request * @param the additional headers to be set to the HTTP request * @return task to wait for returning an empty json object */ pplx::task Get(const web::uri &uri, const utility::string_t &filePath, const std::map headers); /** * @brief Executes a HTTP PUT request with given uri and the content given as json * * @throw mitk::Exception if request went wrong * @param uri defines the URI resulting the target of the HTTP request * @param content the content as json value which should be the body of the request and thus the content of the * created resources * @return task to wait for with resulting json object */ pplx::task Put(const web::uri &uri, const web::json::value *content); /** * @brief Executes a HTTP POST request with given uri and the content given as json * * @throw mitk::Exception if request went wrong * @param uri defines the URI resulting the target of the HTTP request * @param content the content as json value which should be the body of the request and thus the content of the * created resource * @param headers the additional headers to be set to the HTTP request * @return task to wait for with resulting json object */ pplx::task Post(const web::uri &uri, const web::json::value *content, const std::map headers); /** * @brief Executes a HTTP POST request with given uri and the content given as json * * @throw mitk::Exception if request went wrong * @param uri defines the URI resulting the target of the HTTP request * @param content the content as json value which should be the body of the request and thus the content of the * created resource * @param headers the additional headers to be set to the HTTP request * @return task to wait for with resulting json object */ pplx::task Post(const web::uri &uri, const std::vector *content, const std::map headers); private: /** * @brief Use this to create and init a new request with the given headers. If needed, set the body on the resulting * request object to avoid an automatic change of the content type header when setting the body first. */ http_request InitRequest(const std::map headers); + void CheckResponseContentType(web::http::http_response &response); + pplx::task ExecutePost(const web::uri &uri, http_request request); web::http::client::http_client_config m_ClientConfig; }; } // namespace mitk #endif diff --git a/Modules/REST/src/mitkRESTClient.cpp b/Modules/REST/src/mitkRESTClient.cpp index 8b4fa9dd9c..5fc0cb30d0 100644 --- a/Modules/REST/src/mitkRESTClient.cpp +++ b/Modules/REST/src/mitkRESTClient.cpp @@ -1,214 +1,207 @@ /*=================================================================== 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. ===================================================================*/ #include #include #include #include #include using http_client = web::http::client::http_client; using http_request = web::http::http_request; using http_response = web::http::http_response; using methods = web::http::methods; using status_codes = web::http::status_codes; using file_buffer = concurrency::streams::file_buffer; using streambuf = concurrency::streams::streambuf; mitk::RESTClient::RESTClient() { m_ClientConfig.set_validate_certificates(false); } mitk::RESTClient::~RESTClient() {} +void mitk::RESTClient::CheckResponseContentType(web::http::http_response &response) +{ + auto status = response.status_code(); + + if (status_codes::OK != status) + { + MITK_WARN << "Status: " << status; + MITK_WARN << "Response: " << mitk::RESTUtil::convertToUtf8(response.to_string()); + mitkThrow() << mitk::RESTUtil::convertToUtf8(response.to_string()); + } + + auto requestContentType = response.headers().content_type(); + MITK_DEBUG << "Content Type: " << mitk::RESTUtil::convertToUtf8(requestContentType); + MITK_DEBUG << "Body: " << mitk::RESTUtil::convertToUtf8(response.to_string()); + if (requestContentType.find(U("json")) != std::wstring::npos) + { + MITK_DEBUG << "Caution! The given response content type was '" << mitk::RESTUtil::convertToUtf8(requestContentType) + << "' but contains 'json'. So we awesome the answer actually contains a JSON message."; + response.headers().set_content_type(U("application/json")); + } +} + pplx::task mitk::RESTClient::Get(const web::uri &uri, const std::map headers) { auto client = new http_client(uri, m_ClientConfig); http_request request; for (auto param : headers) { request.headers().add(param.first, param.second); } return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); - auto status = response.status_code(); - - if (status_codes::OK != status) - { - MITK_INFO << status; - MITK_INFO << mitk::RESTUtil::convertToUtf8(response.to_string()); - mitkThrow(); - } - - auto requestContentType = response.headers().content_type(); - if (U("application/json") != requestContentType) - response.headers().set_content_type(U("application/json")); + CheckResponseContentType(response); return response.extract_json().get(); } - catch (std::exception &e) + catch (const std::exception &e) { MITK_INFO << e.what(); - mitkThrow() << "Getting response went wrong"; + mitkThrow() << "Getting response went wrong: " << e.what(); } }); } pplx::task mitk::RESTClient::Get(const web::uri &uri, const utility::string_t &filePath, const std::map headers) { auto client = new http_client(uri, m_ClientConfig); auto fileBuffer = std::make_shared>(); http_request request; for (auto param : headers) { request.headers().add(param.first, param.second); } // Open file stream for the specified file path return file_buffer::open(filePath, std::ios::out) .then([=](streambuf outFile) -> pplx::task { *fileBuffer = outFile; return client->request(methods::GET); }) // Write the response body into the file buffer .then([=](http_response response) -> pplx::task { auto status = response.status_code(); if (status_codes::OK != status) - mitkThrow() << "GET ended up with response " << RESTUtil::convertToUtf8(response.to_string()); + { + MITK_INFO << status; + MITK_INFO << mitk::RESTUtil::convertToUtf8(response.to_string()); + mitkThrow() << mitk::RESTUtil::convertToUtf8(response.to_string()); + } return response.body().read_to_end(*fileBuffer); }) // Close the file buffer .then([=](size_t) { return fileBuffer->close(); }) // Return empty JSON object .then([=]() { return web::json::value(); }); } pplx::task mitk::RESTClient::Put(const web::uri &uri, const web::json::value *content) { auto client = new http_client(uri, m_ClientConfig); http_request request(methods::PUT); if (nullptr != content) request.set_body(*content); return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); - auto status = response.status_code(); - if (status_codes::OK != status) - mitkThrow(); - - // Parse content type to application/json if it isn't already. This is - // important if the content type is e.g. application/dicom+json. - auto requestContentType = response.headers().content_type(); - - if (U("application/json") != requestContentType) - response.headers().set_content_type(U("application/json")); + CheckResponseContentType(response); return response.extract_json().get(); } catch (std::exception &e) { MITK_INFO << e.what(); mitkThrow() << "Getting response went wrong"; } }); } pplx::task mitk::RESTClient::Post(const web::uri &uri, const std::vector *content, const std::map headers) { auto request = InitRequest(headers); request.set_method(methods::POST); if (nullptr != content) request.set_body(*content); return ExecutePost(uri, request); } pplx::task mitk::RESTClient::Post(const web::uri &uri, const web::json::value *content, const std::map headers) { auto request = InitRequest(headers); request.set_method(methods::POST); if (nullptr != content) request.set_body(*content); return ExecutePost(uri, request); } http_request mitk::RESTClient::InitRequest(const std::map headers) { http_request request; for (auto param : headers) { request.headers().add(param.first, param.second); } return request; } pplx::task mitk::RESTClient::ExecutePost(const web::uri &uri, http_request request) { auto client = new http_client(uri, m_ClientConfig); return client->request(request).then([=](pplx::task responseTask) { try { auto response = responseTask.get(); - auto status = response.status_code(); - auto requestContentType = response.headers().content_type(); - MITK_INFO << status; - if (status_codes::OK != status) - mitkThrow(); - - MITK_INFO << mitk::RESTUtil::convertToUtf8(requestContentType); - if (U("application/json") != requestContentType) - { - auto json = web::json::value::object(); - json[U("test")] = web::json::value(17); - response.set_body(json); // use random json object in response body to perform return value (Linux Fix) - response.headers().set_content_type(U("application/json")); - } + CheckResponseContentType(response); return response.extract_json().get(); } catch (std::exception &e) { MITK_INFO << e.what(); mitkThrow() << "Getting response went wrong"; } }); }