1 /** 2 * Orthanc - A Lightweight, RESTful DICOM Store 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics 4 * Department, University Hospital of Liege, Belgium 5 * Copyright (C) 2017-2021 Osimis S.A., Belgium 6 * 7 * This program is free software: you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public License 9 * as published by the Free Software Foundation, either version 3 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this program. If not, see 19 * <http://www.gnu.org/licenses/>. 20 **/ 21 22 23 #pragma once 24 25 #include "Enumerations.h" 26 #include "OrthancFramework.h" 27 #include "WebServiceParameters.h" 28 29 #include <string> 30 #include <boost/noncopyable.hpp> 31 #include <boost/shared_ptr.hpp> 32 #include <json/value.h> 33 34 #if !defined(ORTHANC_ENABLE_CURL) 35 # error The macro ORTHANC_ENABLE_CURL must be defined 36 #endif 37 38 #if ORTHANC_ENABLE_CURL != 1 39 # error Support for curl is disabled, cannot use this file 40 #endif 41 42 #if !defined(ORTHANC_ENABLE_SSL) 43 # error The macro ORTHANC_ENABLE_SSL must be defined 44 #endif 45 46 #if !defined(ORTHANC_ENABLE_PKCS11) 47 # error The macro ORTHANC_ENABLE_PKCS11 must be defined 48 #endif 49 50 51 namespace Orthanc 52 { 53 class ORTHANC_PUBLIC HttpClient : public boost::noncopyable 54 { 55 public: 56 typedef std::map<std::string, std::string> HttpHeaders; 57 58 class IRequestBody : public boost::noncopyable 59 { 60 public: ~IRequestBody()61 virtual ~IRequestBody() 62 { 63 } 64 65 virtual bool ReadNextChunk(std::string& chunk) = 0; 66 }; 67 68 class IAnswer : public boost::noncopyable 69 { 70 public: ~IAnswer()71 virtual ~IAnswer() 72 { 73 } 74 75 virtual void AddHeader(const std::string& key, 76 const std::string& value) = 0; 77 78 virtual void AddChunk(const void* data, 79 size_t size) = 0; 80 }; 81 82 private: 83 class CurlHeaders; 84 class CurlRequestBody; 85 class CurlAnswer; 86 class DefaultAnswer; 87 class GlobalParameters; 88 89 struct PImpl; 90 boost::shared_ptr<PImpl> pimpl_; 91 92 std::string url_; 93 std::string credentials_; 94 HttpMethod method_; 95 HttpStatus lastStatus_; 96 std::string body_; // This only makes sense for POST and PUT requests 97 bool isVerbose_; 98 long timeout_; 99 std::string proxy_; 100 bool verifyPeers_; 101 std::string caCertificates_; 102 std::string clientCertificateFile_; 103 std::string clientCertificateKeyFile_; 104 std::string clientCertificateKeyPassword_; 105 bool pkcs11Enabled_; 106 bool headersToLowerCase_; 107 bool redirectionFollowed_; 108 109 // New in Orthanc 1.9.3 to avoid memcpy() 110 bool hasExternalBody_; 111 const void* externalBodyData_; 112 size_t externalBodySize_; 113 114 void Setup(); 115 116 void operator= (const HttpClient&); // Assignment forbidden 117 HttpClient(const HttpClient& base); // Copy forbidden 118 119 bool ApplyInternal(CurlAnswer& answer); 120 121 bool ApplyInternal(std::string& answerBody, 122 HttpHeaders* answerHeaders); 123 124 bool ApplyInternal(Json::Value& answerBody, 125 HttpHeaders* answerHeaders); 126 127 public: 128 HttpClient(); 129 130 HttpClient(const WebServiceParameters& service, 131 const std::string& uri); 132 133 ~HttpClient(); 134 135 void SetUrl(const char* url); 136 137 void SetUrl(const std::string& url); 138 139 const std::string& GetUrl() const; 140 141 void SetMethod(HttpMethod method); 142 143 HttpMethod GetMethod() const; 144 145 void SetTimeout(long seconds); 146 147 long GetTimeout() const; 148 149 void AssignBody(const std::string& data); 150 151 void AssignBody(const void* data, 152 size_t size); 153 154 void SetBody(IRequestBody& body); 155 156 // New in Orthanc 1.9.3: The "data" buffer must have a lifetime 157 // that is longer than the HttpClient object 158 void SetExternalBody(const void* data, 159 size_t size); 160 161 void SetExternalBody(const std::string& data); 162 163 void ClearBody(); 164 165 void SetVerbose(bool isVerbose); 166 167 bool IsVerbose() const; 168 169 void AddHeader(const std::string& key, 170 const std::string& value); 171 172 void ClearHeaders(); 173 174 bool Apply(IAnswer& answer); 175 176 bool Apply(std::string& answerBody); 177 178 bool Apply(Json::Value& answerBody); 179 180 bool Apply(std::string& answerBody, 181 HttpHeaders& answerHeaders); 182 183 bool Apply(Json::Value& answerBody, 184 HttpHeaders& answerHeaders); 185 186 HttpStatus GetLastStatus() const; 187 188 void SetCredentials(const char* username, 189 const char* password); 190 191 void SetProxy(const std::string& proxy); 192 193 void SetHttpsVerifyPeers(bool verify); 194 195 bool IsHttpsVerifyPeers() const; 196 197 void SetHttpsCACertificates(const std::string& certificates); 198 199 const std::string& GetHttpsCACertificates() const; 200 201 void SetClientCertificate(const std::string& certificateFile, 202 const std::string& certificateKeyFile, 203 const std::string& certificateKeyPassword); 204 205 void SetPkcs11Enabled(bool enabled); 206 207 bool IsPkcs11Enabled() const; 208 209 const std::string& GetClientCertificateFile() const; 210 211 const std::string& GetClientCertificateKeyFile() const; 212 213 const std::string& GetClientCertificateKeyPassword() const; 214 215 void SetConvertHeadersToLowerCase(bool lowerCase); 216 217 bool IsConvertHeadersToLowerCase() const; 218 219 void SetRedirectionFollowed(bool follow); 220 221 bool IsRedirectionFollowed() const; 222 223 static void GlobalInitialize(); 224 225 static void GlobalFinalize(); 226 227 static void InitializePkcs11(const std::string& module, 228 const std::string& pin, 229 bool verbose); 230 231 static void ConfigureSsl(bool httpsVerifyPeers, 232 const std::string& httpsCACertificates); 233 234 static void SetDefaultVerbose(bool verbose); 235 236 static void SetDefaultProxy(const std::string& proxy); 237 238 static void SetDefaultTimeout(long timeout); 239 240 void ApplyAndThrowException(IAnswer& answer); 241 242 void ApplyAndThrowException(std::string& answerBody); 243 244 void ApplyAndThrowException(Json::Value& answerBody); 245 246 void ApplyAndThrowException(std::string& answerBody, 247 HttpHeaders& answerHeaders); 248 249 void ApplyAndThrowException(Json::Value& answerBody, 250 HttpHeaders& answerHeaders); 251 252 static void ThrowException(HttpStatus status); 253 }; 254 } 255