# HG changeset patch # User Sebastien Jodogne # Date 1734426822 -3600 # Node ID 5e5069357246fd649a06bd0e9d97169827daf9a5 # Parent 4bd7e199a5e1280be20e7e4bc122e4b271d48ff0 added class OrthancPlugins::RestApiClient diff -r 4bd7e199a5e1 -r 5e5069357246 OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp --- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Mon Dec 16 21:33:32 2024 +0100 +++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Tue Dec 17 10:13:42 2024 +0100 @@ -334,9 +334,9 @@ std::vector headersValues_; public: - explicit PluginHttpHeaders(const std::map& httpHeaders) - { - for (std::map::const_iterator + explicit PluginHttpHeaders(const HttpHeaders& httpHeaders) + { + for (HttpHeaders::const_iterator it = httpHeaders.begin(); it != httpHeaders.end(); ++it) { headersKeys_.push_back(it->first.c_str()); @@ -361,7 +361,7 @@ }; bool MemoryBuffer::RestApiGet(const std::string& uri, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins) { Clear(); @@ -400,7 +400,7 @@ bool MemoryBuffer::RestApiPost(const std::string& uri, const void* body, size_t bodySize, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins) { MemoryBuffer answerHeaders; @@ -422,7 +422,7 @@ bool MemoryBuffer::RestApiPost(const std::string& uri, const Json::Value& body, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins) { std::string s; @@ -1490,7 +1490,7 @@ bool RestApiGetString(std::string& result, const std::string& uri, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins) { MemoryBuffer answer; @@ -1508,7 +1508,7 @@ bool RestApiGet(Json::Value& result, const std::string& uri, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins) { MemoryBuffer answer; @@ -1598,7 +1598,7 @@ bool RestApiPost(Json::Value& result, const std::string& uri, const Json::Value& body, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins) { MemoryBuffer answer; @@ -1963,7 +1963,7 @@ bool OrthancPeers::DoGet(MemoryBuffer& target, size_t index, const std::string& uri, - const std::map& headers) const + const HttpHeaders& headers) const { if (index >= index_.size()) { @@ -1994,7 +1994,7 @@ bool OrthancPeers::DoGet(MemoryBuffer& target, const std::string& name, const std::string& uri, - const std::map& headers) const + const HttpHeaders& headers) const { size_t index; return (LookupName(index, name) && @@ -2005,7 +2005,7 @@ bool OrthancPeers::DoGet(Json::Value& target, size_t index, const std::string& uri, - const std::map& headers) const + const HttpHeaders& headers) const { MemoryBuffer buffer; @@ -2024,7 +2024,7 @@ bool OrthancPeers::DoGet(Json::Value& target, const std::string& name, const std::string& uri, - const std::map& headers) const + const HttpHeaders& headers) const { MemoryBuffer buffer; @@ -2044,7 +2044,7 @@ const std::string& name, const std::string& uri, const std::string& body, - const std::map& headers) const + const HttpHeaders& headers) const { size_t index; return (LookupName(index, name) && @@ -2056,7 +2056,7 @@ size_t index, const std::string& uri, const std::string& body, - const std::map& headers) const + const HttpHeaders& headers) const { MemoryBuffer buffer; @@ -2076,7 +2076,7 @@ const std::string& name, const std::string& uri, const std::string& body, - const std::map& headers) const + const HttpHeaders& headers) const { MemoryBuffer buffer; @@ -2096,7 +2096,7 @@ size_t index, const std::string& uri, const std::string& body, - const std::map& headers) const + const HttpHeaders& headers) const { if (index >= index_.size()) { @@ -2133,7 +2133,7 @@ bool OrthancPeers::DoPut(size_t index, const std::string& uri, const std::string& body, - const std::map& headers) const + const HttpHeaders& headers) const { if (index >= index_.size()) { @@ -2169,7 +2169,7 @@ bool OrthancPeers::DoPut(const std::string& name, const std::string& uri, const std::string& body, - const std::map& headers) const + const HttpHeaders& headers) const { size_t index; return (LookupName(index, name) && @@ -2179,7 +2179,7 @@ bool OrthancPeers::DoDelete(size_t index, const std::string& uri, - const std::map& headers) const + const HttpHeaders& headers) const { if (index >= index_.size()) { @@ -2208,7 +2208,7 @@ bool OrthancPeers::DoDelete(const std::string& name, const std::string& uri, - const std::map& headers) const + const HttpHeaders& headers) const { size_t index; return (LookupName(index, name) && @@ -2923,12 +2923,12 @@ std::vector headersValues_; public: - HeadersWrapper(const HttpClient::HttpHeaders& headers) + HeadersWrapper(const HttpHeaders& headers) { headersKeys_.reserve(headers.size()); headersValues_.reserve(headers.size()); - for (HttpClient::HttpHeaders::const_iterator it = headers.begin(); it != headers.end(); ++it) + for (HttpHeaders::const_iterator it = headers.begin(); it != headers.end(); ++it) { headersKeys_.push_back(it->first.c_str()); headersValues_.push_back(it->second.c_str()); @@ -3076,11 +3076,11 @@ class MemoryAnswer : public HttpClient::IAnswer { private: - HttpClient::HttpHeaders headers_; - ChunkedBuffer body_; + HttpHeaders headers_; + ChunkedBuffer body_; public: - const HttpClient::HttpHeaders& GetHeaders() const + const HttpHeaders& GetHeaders() const { return headers_; } @@ -3168,6 +3168,35 @@ #endif + static void DecodeHttpHeaders(HttpHeaders& target, + const MemoryBuffer& source) + { + Json::Value v; + source.ToJson(v); + + if (v.type() != Json::objectValue) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + + Json::Value::Members members = v.getMemberNames(); + target.clear(); + + for (size_t i = 0; i < members.size(); i++) + { + const Json::Value& h = v[members[i]]; + if (h.type() != Json::stringValue) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + else + { + target[members[i]] = h.asString(); + } + } + } + + void HttpClient::ExecuteWithoutStream(uint16_t& httpStatus, HttpHeaders& answerHeaders, std::string& answerBody, @@ -3208,30 +3237,7 @@ ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error); } - Json::Value v; - answerHeadersBuffer.ToJson(v); - - if (v.type() != Json::objectValue) - { - ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); - } - - Json::Value::Members members = v.getMemberNames(); - answerHeaders.clear(); - - for (size_t i = 0; i < members.size(); i++) - { - const Json::Value& h = v[members[i]]; - if (h.type() != Json::stringValue) - { - ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); - } - else - { - answerHeaders[members[i]] = h.asString(); - } - } - + DecodeHttpHeaders(answerHeaders, answerHeadersBuffer); answerBodyBuffer.ToString(answerBody); } @@ -4061,7 +4067,7 @@ } #endif - void GetHttpHeaders(std::map& result, const OrthancPluginHttpRequest* request) + void GetHttpHeaders(HttpHeaders& result, const OrthancPluginHttpRequest* request) { result.clear(); @@ -4114,4 +4120,135 @@ SetPluginProperty(pluginIdentifier, _OrthancPluginProperty_OrthancExplorer, javascript); #endif } + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + RestApiClient::RestApiClient() : + method_(OrthancPluginHttpMethod_Get), + path_("/"), + afterPlugins_(false), + httpStatus_(0) + { + } +#endif + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + void RestApiClient::AddRequestHeader(const std::string& key, + const std::string& value) + { + if (requestHeaders_.find(key) == requestHeaders_.end()) + { + requestHeaders_[key] = value; + } + else + { + ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls); + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + bool RestApiClient::Execute() + { + if (requestBody_.size() > 0xffffffffu) + { + ORTHANC_PLUGINS_LOG_ERROR("Cannot handle body size > 4GB"); + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + + PluginHttpHeaders converted(requestHeaders_); + + MemoryBuffer body; + MemoryBuffer headers; + + OrthancPluginErrorCode code = OrthancPluginCallRestApi(GetGlobalContext(), *body, *headers, &httpStatus_, method_, path_.c_str(), + requestHeaders_.size(), converted.GetKeys(), converted.GetValues(), + requestBody_.c_str(), requestBody_.size(), afterPlugins_ ? 1 : 0); + + answerHeaders_.clear(); + answerBody_.clear(); + + if (code == OrthancPluginErrorCode_Success) + { + if (httpStatus_ == 0) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); + } + + DecodeHttpHeaders(answerHeaders_, headers); + body.ToString(answerBody_); + return true; + } + else + { + if (code == OrthancPluginErrorCode_UnknownResource || + code == OrthancPluginErrorCode_InexistentItem) + { + httpStatus_ = 404; + return false; + } + else + { + ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code); + } + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + uint16_t RestApiClient::GetHttpStatus() const + { + if (httpStatus_ == 0) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls); + } + else + { + return httpStatus_; + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + bool RestApiClient::LookupAnswerHeader(std::string& value, + const std::string& key) const + { + if (httpStatus_ == 0) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls); + } + else + { + HttpHeaders::const_iterator found = answerHeaders_.find(key); + if (found == answerHeaders_.end()) + { + return false; + } + else + { + value = found->second; + return true; + } + } + } +#endif + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + const std::string& RestApiClient::GetAnswerBody() const + { + if (httpStatus_ == 0) + { + ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls); + } + else + { + return answerBody_; + } + } +#endif } diff -r 4bd7e199a5e1 -r 5e5069357246 OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h --- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h Mon Dec 16 21:33:32 2024 +0100 +++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h Tue Dec 17 10:13:42 2024 +0100 @@ -170,6 +170,8 @@ namespace OrthancPlugins { + typedef std::map HttpHeaders; + typedef void (*RestCallback) (OrthancPluginRestOutput* output, const char* url, const OrthancPluginHttpRequest* request); @@ -257,7 +259,7 @@ bool applyPlugins); bool RestApiGet(const std::string& uri, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins); bool RestApiPost(const std::string& uri, @@ -277,13 +279,13 @@ #if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 bool RestApiPost(const std::string& uri, const Json::Value& body, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins); bool RestApiPost(const std::string& uri, const void* body, size_t bodySize, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins); #endif @@ -581,7 +583,7 @@ bool RestApiGet(Json::Value& result, const std::string& uri, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins); bool RestApiGetString(std::string& result, @@ -590,7 +592,7 @@ bool RestApiGetString(std::string& result, const std::string& uri, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins); bool RestApiPost(std::string& result, @@ -609,7 +611,7 @@ bool RestApiPost(Json::Value& result, const std::string& uri, const Json::Value& body, - const std::map& httpHeaders, + const HttpHeaders& httpHeaders, bool applyPlugins); #endif @@ -829,64 +831,64 @@ bool DoGet(MemoryBuffer& target, size_t index, const std::string& uri, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoGet(MemoryBuffer& target, const std::string& name, const std::string& uri, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoGet(Json::Value& target, size_t index, const std::string& uri, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoGet(Json::Value& target, const std::string& name, const std::string& uri, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoPost(MemoryBuffer& target, size_t index, const std::string& uri, const std::string& body, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoPost(MemoryBuffer& target, const std::string& name, const std::string& uri, const std::string& body, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoPost(Json::Value& target, size_t index, const std::string& uri, const std::string& body, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoPost(Json::Value& target, const std::string& name, const std::string& uri, const std::string& body, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoPut(size_t index, const std::string& uri, const std::string& body, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoPut(const std::string& name, const std::string& uri, const std::string& body, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoDelete(size_t index, const std::string& uri, - const std::map& headers) const; + const HttpHeaders& headers) const; bool DoDelete(const std::string& name, const std::string& uri, - const std::map& headers) const; + const HttpHeaders& headers) const; }; #endif @@ -996,8 +998,6 @@ class HttpClient : public boost::noncopyable { public: - typedef std::map HttpHeaders; - class IRequestBody : public boost::noncopyable { public: @@ -1397,7 +1397,7 @@ }; // helper method to convert Http headers from the plugin SDK to a std::map -void GetHttpHeaders(std::map& result, const OrthancPluginHttpRequest* request); +void GetHttpHeaders(HttpHeaders& result, const OrthancPluginHttpRequest* request); #if HAS_ORTHANC_PLUGIN_WEBDAV == 1 class IWebDavCollection : public boost::noncopyable @@ -1508,4 +1508,88 @@ void ExtendOrthancExplorer(const std::string& pluginIdentifier, const std::string& javascript); + + +#if HAS_ORTHANC_PLUGIN_GENERIC_CALL_REST_API == 1 + class RestApiClient : public boost::noncopyable + { + private: + // Request + OrthancPluginHttpMethod method_; + std::string path_; + HttpHeaders requestHeaders_; + std::string requestBody_; + bool afterPlugins_; + + // Answer + uint16_t httpStatus_; + HttpHeaders answerHeaders_; + std::string answerBody_; + + public: + RestApiClient(); + + void SetMethod(OrthancPluginHttpMethod method) + { + method_ = method; + } + + OrthancPluginHttpMethod GetMethod() const + { + return method_; + } + + void SetPath(const std::string& path) + { + path_ = path; + } + + const std::string& GetPath() const + { + return path_; + } + + void AddRequestHeader(const std::string& key, + const std::string& value); + + const HttpHeaders& GetRequestHeaders() const + { + return requestHeaders_; + } + + void SetRequestBody(const std::string& body) + { + requestBody_ = body; + } + + void SwapRequestBody(std::string& body) + { + requestBody_.swap(body); + } + + void SetAfterPlugins(bool afterPlugins) + { + afterPlugins_ = afterPlugins; + } + + bool IsAfterPlugins() const + { + return afterPlugins_; + } + + const std::string& GetRequestBody() const + { + return requestBody_; + } + + bool Execute(); + + uint16_t GetHttpStatus() const; + + bool LookupAnswerHeader(std::string& value, + const std::string& key) const; + + const std::string& GetAnswerBody() const; + }; +#endif }