Mercurial > hg > orthanc
comparison Plugins/Samples/Common/OrthancPluginCppWrapper.cpp @ 3387:a48d652f1500
new function OrthancPluginHttpClientChunkedBody(), new class OrthancPlugins::HttpClient
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 05 Jun 2019 17:17:48 +0200 |
parents | 0f721f015b85 |
children | 18cd4951fccc |
comparison
equal
deleted
inserted
replaced
3386:af9432e46c07 | 3387:a48d652f1500 |
---|---|
438 bool HttpDelete(const std::string& url, | 438 bool HttpDelete(const std::string& url, |
439 const std::string& username, | 439 const std::string& username, |
440 const std::string& password) | 440 const std::string& password) |
441 { | 441 { |
442 OrthancPluginErrorCode error = OrthancPluginHttpDelete | 442 OrthancPluginErrorCode error = OrthancPluginHttpDelete |
443 (GetGlobalContext(), url.c_str(), | 443 (GetGlobalContext(), url.c_str(), |
444 username.empty() ? NULL : username.c_str(), | 444 username.empty() ? NULL : username.c_str(), |
445 password.empty() ? NULL : password.c_str()); | 445 password.empty() ? NULL : password.c_str()); |
446 | 446 |
447 if (error == OrthancPluginErrorCode_Success) | 447 if (error == OrthancPluginErrorCode_Success) |
448 { | 448 { |
449 return true; | 449 return true; |
450 } | 450 } |
589 return false; | 589 return false; |
590 } | 590 } |
591 | 591 |
592 switch (configuration_[key].type()) | 592 switch (configuration_[key].type()) |
593 { | 593 { |
594 case Json::intValue: | 594 case Json::intValue: |
595 target = configuration_[key].asInt(); | 595 target = configuration_[key].asInt(); |
596 return true; | 596 return true; |
597 | 597 |
598 case Json::uintValue: | 598 case Json::uintValue: |
599 target = configuration_[key].asUInt(); | 599 target = configuration_[key].asUInt(); |
600 return true; | 600 return true; |
601 | 601 |
602 default: | 602 default: |
603 LogError("The configuration option \"" + GetPath(key) + | 603 LogError("The configuration option \"" + GetPath(key) + |
604 "\" is not an integer as expected"); | 604 "\" is not an integer as expected"); |
605 | 605 |
606 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | 606 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); |
607 } | 607 } |
608 } | 608 } |
609 | 609 |
610 | 610 |
611 bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target, | 611 bool OrthancConfiguration::LookupUnsignedIntegerValue(unsigned int& target, |
665 return false; | 665 return false; |
666 } | 666 } |
667 | 667 |
668 switch (configuration_[key].type()) | 668 switch (configuration_[key].type()) |
669 { | 669 { |
670 case Json::realValue: | 670 case Json::realValue: |
671 target = configuration_[key].asFloat(); | 671 target = configuration_[key].asFloat(); |
672 return true; | 672 return true; |
673 | 673 |
674 case Json::intValue: | 674 case Json::intValue: |
675 target = static_cast<float>(configuration_[key].asInt()); | 675 target = static_cast<float>(configuration_[key].asInt()); |
676 return true; | 676 return true; |
677 | 677 |
678 case Json::uintValue: | 678 case Json::uintValue: |
679 target = static_cast<float>(configuration_[key].asUInt()); | 679 target = static_cast<float>(configuration_[key].asUInt()); |
680 return true; | 680 return true; |
681 | 681 |
682 default: | 682 default: |
683 LogError("The configuration option \"" + GetPath(key) + | 683 LogError("The configuration option \"" + GetPath(key) + |
684 "\" is not an integer as expected"); | 684 "\" is not an integer as expected"); |
685 | 685 |
686 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); | 686 ORTHANC_PLUGINS_THROW_EXCEPTION(BadFileFormat); |
687 } | 687 } |
688 } | 688 } |
689 | 689 |
690 | 690 |
691 bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target, | 691 bool OrthancConfiguration::LookupListOfStrings(std::list<std::string>& target, |
701 return false; | 701 return false; |
702 } | 702 } |
703 | 703 |
704 switch (configuration_[key].type()) | 704 switch (configuration_[key].type()) |
705 { | 705 { |
706 case Json::arrayValue: | 706 case Json::arrayValue: |
707 { | |
708 bool ok = true; | |
709 | |
710 for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++) | |
711 { | 707 { |
712 if (configuration_[key][i].type() == Json::stringValue) | 708 bool ok = true; |
709 | |
710 for (Json::Value::ArrayIndex i = 0; ok && i < configuration_[key].size(); i++) | |
713 { | 711 { |
714 target.push_back(configuration_[key][i].asString()); | 712 if (configuration_[key][i].type() == Json::stringValue) |
713 { | |
714 target.push_back(configuration_[key][i].asString()); | |
715 } | |
716 else | |
717 { | |
718 ok = false; | |
719 } | |
715 } | 720 } |
716 else | 721 |
722 if (ok) | |
717 { | 723 { |
718 ok = false; | 724 return true; |
719 } | 725 } |
726 | |
727 break; | |
720 } | 728 } |
721 | 729 |
722 if (ok) | 730 case Json::stringValue: |
723 { | 731 if (allowSingleString) |
724 return true; | 732 { |
725 } | 733 target.push_back(configuration_[key].asString()); |
726 | 734 return true; |
727 break; | 735 } |
728 } | 736 |
729 | 737 break; |
730 case Json::stringValue: | 738 |
731 if (allowSingleString) | 739 default: |
732 { | 740 break; |
733 target.push_back(configuration_[key].asString()); | |
734 return true; | |
735 } | |
736 | |
737 break; | |
738 | |
739 default: | |
740 break; | |
741 } | 741 } |
742 | 742 |
743 LogError("The configuration option \"" + GetPath(key) + | 743 LogError("The configuration option \"" + GetPath(key) + |
744 "\" is not a list of strings as expected"); | 744 "\" is not a list of strings as expected"); |
745 | 745 |
756 if (LookupListOfStrings(lst, key, allowSingleString)) | 756 if (LookupListOfStrings(lst, key, allowSingleString)) |
757 { | 757 { |
758 target.clear(); | 758 target.clear(); |
759 | 759 |
760 for (std::list<std::string>::const_iterator | 760 for (std::list<std::string>::const_iterator |
761 it = lst.begin(); it != lst.end(); ++it) | 761 it = lst.begin(); it != lst.end(); ++it) |
762 { | 762 { |
763 target.insert(*it); | 763 target.insert(*it); |
764 } | 764 } |
765 | 765 |
766 return true; | 766 return true; |
939 uint32_t height, | 939 uint32_t height, |
940 uint32_t pitch, | 940 uint32_t pitch, |
941 void* buffer) | 941 void* buffer) |
942 { | 942 { |
943 image_ = OrthancPluginCreateImageAccessor | 943 image_ = OrthancPluginCreateImageAccessor |
944 (GetGlobalContext(), format, width, height, pitch, buffer); | 944 (GetGlobalContext(), format, width, height, pitch, buffer); |
945 | 945 |
946 if (image_ == NULL) | 946 if (image_ == NULL) |
947 { | 947 { |
948 LogError("Cannot create an image accessor"); | 948 LogError("Cannot create an image accessor"); |
949 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | 949 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); |
1141 | 1141 |
1142 #endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */ | 1142 #endif /* HAS_ORTHANC_PLUGIN_FIND_MATCHER == 1 */ |
1143 | 1143 |
1144 void AnswerJson(const Json::Value& value, | 1144 void AnswerJson(const Json::Value& value, |
1145 OrthancPluginRestOutput* output | 1145 OrthancPluginRestOutput* output |
1146 ) | 1146 ) |
1147 { | 1147 { |
1148 Json::StyledWriter writer; | 1148 Json::StyledWriter writer; |
1149 std::string bodyString = writer.write(value); | 1149 std::string bodyString = writer.write(value); |
1150 | 1150 |
1151 OrthancPluginAnswerBuffer(GetGlobalContext(), output, bodyString.c_str(), bodyString.size(), "application/json"); | 1151 OrthancPluginAnswerBuffer(GetGlobalContext(), output, bodyString.c_str(), bodyString.size(), "application/json"); |
1152 } | 1152 } |
1153 | 1153 |
1154 void AnswerString(const std::string& answer, | 1154 void AnswerString(const std::string& answer, |
1155 const char* mimeType, | 1155 const char* mimeType, |
1156 OrthancPluginRestOutput* output | 1156 OrthancPluginRestOutput* output |
1157 ) | 1157 ) |
1158 { | 1158 { |
1159 OrthancPluginAnswerBuffer(GetGlobalContext(), output, answer.c_str(), answer.size(), mimeType); | 1159 OrthancPluginAnswerBuffer(GetGlobalContext(), output, answer.c_str(), answer.size(), mimeType); |
1160 } | 1160 } |
1161 | 1161 |
1162 void AnswerHttpError(uint16_t httpError, OrthancPluginRestOutput *output) | 1162 void AnswerHttpError(uint16_t httpError, OrthancPluginRestOutput *output) |
1352 } | 1352 } |
1353 | 1353 |
1354 // Parse the version of the Orthanc core | 1354 // Parse the version of the Orthanc core |
1355 int aa, bb, cc; | 1355 int aa, bb, cc; |
1356 if ( | 1356 if ( |
1357 #ifdef _MSC_VER | 1357 #ifdef _MSC_VER |
1358 sscanf_s | 1358 sscanf_s |
1359 #else | 1359 #else |
1360 sscanf | 1360 sscanf |
1361 #endif | 1361 #endif |
1362 (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 || | 1362 (GetGlobalContext()->orthancVersion, "%4d.%4d.%4d", &aa, &bb, &cc) != 3 || |
1363 aa < 0 || | 1363 aa < 0 || |
1364 bb < 0 || | 1364 bb < 0 || |
1365 cc < 0) | 1365 cc < 0) |
1366 { | 1366 { |
1367 return false; | 1367 return false; |
1368 } | 1368 } |
1369 | 1369 |
1370 unsigned int a = static_cast<unsigned int>(aa); | 1370 unsigned int a = static_cast<unsigned int>(aa); |
1588 } | 1588 } |
1589 | 1589 |
1590 OrthancPlugins::MemoryBuffer answer; | 1590 OrthancPlugins::MemoryBuffer answer; |
1591 uint16_t status; | 1591 uint16_t status; |
1592 OrthancPluginErrorCode code = OrthancPluginCallPeerApi | 1592 OrthancPluginErrorCode code = OrthancPluginCallPeerApi |
1593 (GetGlobalContext(), *answer, NULL, &status, peers_, | 1593 (GetGlobalContext(), *answer, NULL, &status, peers_, |
1594 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(), | 1594 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Get, uri.c_str(), |
1595 0, NULL, NULL, NULL, 0, timeout_); | 1595 0, NULL, NULL, NULL, 0, timeout_); |
1596 | 1596 |
1597 if (code == OrthancPluginErrorCode_Success) | 1597 if (code == OrthancPluginErrorCode_Success) |
1598 { | 1598 { |
1599 target.Swap(answer); | 1599 target.Swap(answer); |
1600 return (status == 200); | 1600 return (status == 200); |
1712 } | 1712 } |
1713 | 1713 |
1714 OrthancPlugins::MemoryBuffer answer; | 1714 OrthancPlugins::MemoryBuffer answer; |
1715 uint16_t status; | 1715 uint16_t status; |
1716 OrthancPluginErrorCode code = OrthancPluginCallPeerApi | 1716 OrthancPluginErrorCode code = OrthancPluginCallPeerApi |
1717 (GetGlobalContext(), *answer, NULL, &status, peers_, | 1717 (GetGlobalContext(), *answer, NULL, &status, peers_, |
1718 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(), | 1718 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Post, uri.c_str(), |
1719 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); | 1719 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); |
1720 | 1720 |
1721 if (code == OrthancPluginErrorCode_Success) | 1721 if (code == OrthancPluginErrorCode_Success) |
1722 { | 1722 { |
1723 target.Swap(answer); | 1723 target.Swap(answer); |
1724 return (status == 200); | 1724 return (status == 200); |
1740 } | 1740 } |
1741 | 1741 |
1742 OrthancPlugins::MemoryBuffer answer; | 1742 OrthancPlugins::MemoryBuffer answer; |
1743 uint16_t status; | 1743 uint16_t status; |
1744 OrthancPluginErrorCode code = OrthancPluginCallPeerApi | 1744 OrthancPluginErrorCode code = OrthancPluginCallPeerApi |
1745 (GetGlobalContext(), *answer, NULL, &status, peers_, | 1745 (GetGlobalContext(), *answer, NULL, &status, peers_, |
1746 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(), | 1746 static_cast<uint32_t>(index), OrthancPluginHttpMethod_Put, uri.c_str(), |
1747 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); | 1747 0, NULL, NULL, body.empty() ? NULL : body.c_str(), body.size(), timeout_); |
1748 | 1748 |
1749 if (code == OrthancPluginErrorCode_Success) | 1749 if (code == OrthancPluginErrorCode_Success) |
1750 { | 1750 { |
1751 return (status == 200); | 1751 return (status == 200); |
1752 } | 1752 } |
1998 { | 1998 { |
1999 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer); | 1999 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_NullPointer); |
2000 } | 2000 } |
2001 | 2001 |
2002 OrthancPluginJob* orthanc = OrthancPluginCreateJob( | 2002 OrthancPluginJob* orthanc = OrthancPluginCreateJob( |
2003 GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(), | 2003 GetGlobalContext(), job, CallbackFinalize, job->jobType_.c_str(), |
2004 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized, | 2004 CallbackGetProgress, CallbackGetContent, CallbackGetSerialized, |
2005 CallbackStep, CallbackStop, CallbackReset); | 2005 CallbackStep, CallbackStop, CallbackReset); |
2006 | 2006 |
2007 if (orthanc == NULL) | 2007 if (orthanc == NULL) |
2008 { | 2008 { |
2009 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin); | 2009 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(OrthancPluginErrorCode_Plugin); |
2010 } | 2010 } |
2053 const boost::posix_time::time_duration diff = stop - start_; | 2053 const boost::posix_time::time_duration diff = stop - start_; |
2054 OrthancPluginSetMetricsValue(GetGlobalContext(), name_.c_str(), diff.total_milliseconds(), | 2054 OrthancPluginSetMetricsValue(GetGlobalContext(), name_.c_str(), diff.total_milliseconds(), |
2055 OrthancPluginMetricsType_Timer); | 2055 OrthancPluginMetricsType_Timer); |
2056 } | 2056 } |
2057 #endif | 2057 #endif |
2058 | |
2059 | |
2060 | |
2061 #if HAS_ORTHANC_PLUGIN_HTTP_CHUNKED_BODY == 1 | |
2062 class HttpClient::ChunkedBody : public boost::noncopyable | |
2063 { | |
2064 private: | |
2065 static ChunkedBody& GetObject(void* body) | |
2066 { | |
2067 assert(body != NULL); | |
2068 return *reinterpret_cast<ChunkedBody*>(body); | |
2069 } | |
2070 | |
2071 IChunkedBody& body_; | |
2072 bool done_; | |
2073 std::string chunk_; | |
2074 | |
2075 public: | |
2076 ChunkedBody(IChunkedBody& body) : | |
2077 body_(body), | |
2078 done_(false) | |
2079 { | |
2080 } | |
2081 | |
2082 static uint8_t IsDone(void* body) | |
2083 { | |
2084 return GetObject(body).done_; | |
2085 } | |
2086 | |
2087 static const void* GetChunkData(void* body) | |
2088 { | |
2089 return GetObject(body).chunk_.c_str(); | |
2090 } | |
2091 | |
2092 static uint32_t GetChunkSize(void* body) | |
2093 { | |
2094 return static_cast<uint32_t>(GetObject(body).chunk_.size()); | |
2095 } | |
2096 | |
2097 static OrthancPluginErrorCode Next(void* body) | |
2098 { | |
2099 ChunkedBody& that = GetObject(body); | |
2100 | |
2101 if (that.done_) | |
2102 { | |
2103 return OrthancPluginErrorCode_BadSequenceOfCalls; | |
2104 } | |
2105 else | |
2106 { | |
2107 try | |
2108 { | |
2109 that.done_ = !that.body_.ReadNextChunk(that.chunk_); | |
2110 return OrthancPluginErrorCode_Success; | |
2111 } | |
2112 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) | |
2113 { | |
2114 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); | |
2115 } | |
2116 catch (...) | |
2117 { | |
2118 return OrthancPluginErrorCode_InternalError; | |
2119 } | |
2120 } | |
2121 } | |
2122 }; | |
2123 #endif | |
2124 | |
2125 HttpClient::HttpClient() : | |
2126 httpStatus_(0), | |
2127 method_(OrthancPluginHttpMethod_Get), | |
2128 timeout_(0), | |
2129 pkcs11_(false), | |
2130 chunkedBody_(NULL) | |
2131 { | |
2132 } | |
2133 | |
2134 | |
2135 void HttpClient::SetCredentials(const std::string& username, | |
2136 const std::string& password) | |
2137 { | |
2138 username_ = username; | |
2139 password_ = password; | |
2140 } | |
2141 | |
2142 | |
2143 void HttpClient::ClearCredentials() | |
2144 { | |
2145 username_.empty(); | |
2146 password_.empty(); | |
2147 } | |
2148 | |
2149 | |
2150 void HttpClient::SetCertificate(const std::string& certificateFile, | |
2151 const std::string& keyFile, | |
2152 const std::string& keyPassword) | |
2153 { | |
2154 certificateFile_ = certificateFile; | |
2155 certificateKeyFile_ = keyFile; | |
2156 certificateKeyPassword_ = keyPassword; | |
2157 } | |
2158 | |
2159 | |
2160 void HttpClient::ClearCertificate() | |
2161 { | |
2162 certificateFile_.clear(); | |
2163 certificateKeyFile_.clear(); | |
2164 certificateKeyPassword_.clear(); | |
2165 } | |
2166 | |
2167 | |
2168 void HttpClient::ClearBody() | |
2169 { | |
2170 body_.clear(); | |
2171 chunkedBody_ = NULL; | |
2172 } | |
2173 | |
2174 | |
2175 void HttpClient::SwapBody(std::string& body) | |
2176 { | |
2177 body_.swap(body); | |
2178 chunkedBody_ = NULL; | |
2179 } | |
2180 | |
2181 | |
2182 void HttpClient::SetBody(const std::string& body) | |
2183 { | |
2184 body_ = body; | |
2185 chunkedBody_ = NULL; | |
2186 } | |
2187 | |
2188 | |
2189 #if HAS_ORTHANC_PLUGIN_HTTP_CHUNKED_BODY == 1 | |
2190 void HttpClient::SetBody(IChunkedBody& body) | |
2191 { | |
2192 body_.clear(); | |
2193 chunkedBody_ = &body; | |
2194 } | |
2195 #endif | |
2196 | |
2197 | |
2198 void HttpClient::Execute() | |
2199 { | |
2200 std::vector<const char*> headersKeys; | |
2201 std::vector<const char*> headersValues; | |
2202 | |
2203 headersKeys.reserve(headers_.size()); | |
2204 headersValues.reserve(headers_.size()); | |
2205 | |
2206 for (HttpHeaders::const_iterator it = headers_.begin(); | |
2207 it != headers_.end(); ++it) | |
2208 { | |
2209 headersKeys.push_back(it->first.c_str()); | |
2210 headersValues.push_back(it->second.c_str()); | |
2211 } | |
2212 | |
2213 OrthancPluginErrorCode error; | |
2214 | |
2215 if (chunkedBody_ == NULL) | |
2216 { | |
2217 error = OrthancPluginHttpClient( | |
2218 GetGlobalContext(), | |
2219 *answerBody_, | |
2220 *answerHeaders_, | |
2221 &httpStatus_, | |
2222 method_, | |
2223 url_.c_str(), | |
2224 headersKeys.size(), | |
2225 headersKeys.empty() ? NULL : &headersKeys[0], | |
2226 headersValues.empty() ? NULL : &headersValues[0], | |
2227 body_.empty() ? NULL : body_.c_str(), | |
2228 body_.size(), | |
2229 username_.empty() ? NULL : username_.c_str(), | |
2230 password_.empty() ? NULL : password_.c_str(), | |
2231 timeout_, | |
2232 certificateFile_.empty() ? NULL : certificateFile_.c_str(), | |
2233 certificateFile_.empty() ? NULL : certificateKeyFile_.c_str(), | |
2234 certificateFile_.empty() ? NULL : certificateKeyPassword_.c_str(), | |
2235 pkcs11_ ? 1 : 0); | |
2236 } | |
2237 else | |
2238 { | |
2239 #if HAS_ORTHANC_PLUGIN_HTTP_CHUNKED_BODY != 1 | |
2240 error = OrthancPluginErrorCode_InternalError; | |
2241 #else | |
2242 ChunkedBody wrapper(*chunkedBody_); | |
2243 | |
2244 error = OrthancPluginHttpClientChunkedBody( | |
2245 GetGlobalContext(), | |
2246 *answerBody_, | |
2247 *answerHeaders_, | |
2248 &httpStatus_, | |
2249 method_, | |
2250 url_.c_str(), | |
2251 headersKeys.size(), | |
2252 headersKeys.empty() ? NULL : &headersKeys[0], | |
2253 headersValues.empty() ? NULL : &headersValues[0], | |
2254 username_.empty() ? NULL : username_.c_str(), | |
2255 password_.empty() ? NULL : password_.c_str(), | |
2256 timeout_, | |
2257 certificateFile_.empty() ? NULL : certificateFile_.c_str(), | |
2258 certificateFile_.empty() ? NULL : certificateKeyFile_.c_str(), | |
2259 certificateFile_.empty() ? NULL : certificateKeyPassword_.c_str(), | |
2260 pkcs11_ ? 1 : 0, | |
2261 &wrapper, | |
2262 ChunkedBody::IsDone, | |
2263 ChunkedBody::GetChunkData, | |
2264 ChunkedBody::GetChunkSize, | |
2265 ChunkedBody::Next); | |
2266 #endif | |
2267 } | |
2268 | |
2269 if (error != OrthancPluginErrorCode_Success) | |
2270 { | |
2271 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(error); | |
2272 } | |
2273 } | |
2058 } | 2274 } |