Mercurial > hg > orthanc
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 { |