comparison Core/HttpClient.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 af9432e46c07
children ad434967a68c
comparison
equal deleted inserted replaced
3386:af9432e46c07 3387:a48d652f1500
199 return isChunkedTransfer_; 199 return isChunkedTransfer_;
200 } 200 }
201 }; 201 };
202 202
203 203
204 class HttpClient::CurlBodyStream : public boost::noncopyable 204 class HttpClient::CurlChunkedBody : public boost::noncopyable
205 { 205 {
206 private: 206 private:
207 HttpClient::IBodyStream* stream_; 207 HttpClient::IChunkedBody* body_;
208 std::string buffer_; 208 std::string buffer_;
209 209
210 size_t CallbackInternal(char* curlBuffer, 210 size_t CallbackInternal(char* curlBuffer,
211 size_t curlBufferSize) 211 size_t curlBufferSize)
212 { 212 {
213 if (stream_ == NULL) 213 if (body_ == NULL)
214 { 214 {
215 throw OrthancException(ErrorCode_BadSequenceOfCalls); 215 throw OrthancException(ErrorCode_BadSequenceOfCalls);
216 } 216 }
217 217
218 if (curlBufferSize == 0) 218 if (curlBufferSize == 0)
219 { 219 {
220 throw OrthancException(ErrorCode_InternalError); 220 throw OrthancException(ErrorCode_InternalError);
221 } 221 }
222 222
223 // Read chunks from the stream so as to fill the target buffer 223 // Read chunks from the body stream so as to fill the target buffer
224 std::string chunk; 224 std::string chunk;
225 225
226 while (buffer_.size() < curlBufferSize && 226 while (buffer_.size() < curlBufferSize &&
227 stream_->ReadNextChunk(chunk)) 227 body_->ReadNextChunk(chunk))
228 { 228 {
229 buffer_ += chunk; 229 buffer_ += chunk;
230 } 230 }
231 231
232 size_t s = std::min(buffer_.size(), curlBufferSize); 232 size_t s = std::min(buffer_.size(), curlBufferSize);
241 241
242 return s; 242 return s;
243 } 243 }
244 244
245 public: 245 public:
246 CurlBodyStream() : 246 CurlChunkedBody() :
247 stream_(NULL) 247 body_(NULL)
248 { 248 {
249 } 249 }
250 250
251 void SetStream(HttpClient::IBodyStream& stream) 251 void SetBody(HttpClient::IChunkedBody& body)
252 { 252 {
253 stream_ = &stream; 253 body_ = &body;
254 buffer_.clear(); 254 buffer_.clear();
255 } 255 }
256 256
257 void Clear() 257 void Clear()
258 { 258 {
259 stream_ = NULL; 259 body_ = NULL;
260 buffer_.clear(); 260 buffer_.clear();
261 } 261 }
262 262
263 bool IsValid() const 263 bool IsValid() const
264 { 264 {
265 return stream_ != NULL; 265 return body_ != NULL;
266 } 266 }
267 267
268 static size_t Callback(char *buffer, 268 static size_t Callback(char *buffer,
269 size_t size, 269 size_t size,
270 size_t nitems, 270 size_t nitems,
271 void *userdata) 271 void *userdata)
272 { 272 {
273 try 273 try
274 { 274 {
275 HttpClient::CurlBodyStream* stream = reinterpret_cast<HttpClient::CurlBodyStream*>(userdata); 275 HttpClient::CurlChunkedBody* body = reinterpret_cast<HttpClient::CurlChunkedBody*>(userdata);
276 276
277 if (stream == NULL) 277 if (body == NULL)
278 { 278 {
279 throw OrthancException(ErrorCode_NullPointer); 279 throw OrthancException(ErrorCode_NullPointer);
280 } 280 }
281 else 281 else
282 { 282 {
283 return stream->CallbackInternal(buffer, size * nitems); 283 return body->CallbackInternal(buffer, size * nitems);
284 } 284 }
285 } 285 }
286 catch (OrthancException& e) 286 catch (OrthancException& e)
287 { 287 {
288 LOG(ERROR) << "Exception while streaming HTTP body: " << e.What(); 288 LOG(ERROR) << "Exception while streaming HTTP body: " << e.What();
402 { 402 {
403 CURL* curl_; 403 CURL* curl_;
404 CurlHeaders defaultPostHeaders_; 404 CurlHeaders defaultPostHeaders_;
405 CurlHeaders defaultChunkedHeaders_; 405 CurlHeaders defaultChunkedHeaders_;
406 CurlHeaders userHeaders_; 406 CurlHeaders userHeaders_;
407 CurlBodyStream bodyStream_; 407 CurlChunkedBody chunkedBody_;
408 }; 408 };
409 409
410 410
411 void HttpClient::ThrowException(HttpStatus status) 411 void HttpClient::ThrowException(HttpStatus status)
412 { 412 {
602 602
603 603
604 void HttpClient::SetBody(const std::string& data) 604 void HttpClient::SetBody(const std::string& data)
605 { 605 {
606 body_ = data; 606 body_ = data;
607 pimpl_->bodyStream_.Clear(); 607 pimpl_->chunkedBody_.Clear();
608 } 608 }
609 609
610 610
611 void HttpClient::SetBodyStream(IBodyStream& stream) 611 void HttpClient::SetBody(IChunkedBody& body)
612 { 612 {
613 pimpl_->bodyStream_.SetStream(stream); 613 body_.clear();
614 pimpl_->chunkedBody_.SetBody(body);
614 } 615 }
615 616
616 617
617 void HttpClient::ClearBodyStream() 618 void HttpClient::ClearBody()
618 { 619 {
619 pimpl_->bodyStream_.Clear(); 620 body_.clear();
621 pimpl_->chunkedBody_.Clear();
620 } 622 }
621 623
622 624
623 void HttpClient::SetVerbose(bool isVerbose) 625 void HttpClient::SetVerbose(bool isVerbose)
624 { 626 {
823 !pimpl_->userHeaders_.HasExpect()) 825 !pimpl_->userHeaders_.HasExpect())
824 { 826 {
825 LOG(INFO) << "For performance, the HTTP header \"Expect\" should be set to empty string in POST/PUT requests"; 827 LOG(INFO) << "For performance, the HTTP header \"Expect\" should be set to empty string in POST/PUT requests";
826 } 828 }
827 829
828 if (pimpl_->bodyStream_.IsValid()) 830 if (pimpl_->chunkedBody_.IsValid())
829 { 831 {
830 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_READFUNCTION, CurlBodyStream::Callback)); 832 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_READFUNCTION, CurlChunkedBody::Callback));
831 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_READDATA, &pimpl_->bodyStream_)); 833 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_READDATA, &pimpl_->chunkedBody_));
832 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L)); 834 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L));
833 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, -1L)); 835 CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, -1L));
834 836
835 if (pimpl_->userHeaders_.IsEmpty()) 837 if (pimpl_->userHeaders_.IsEmpty())
836 { 838 {