diff --git a/src/controllerclientimpl.cpp b/src/controllerclientimpl.cpp index ebff0fd6..5fbd905a 100644 --- a/src/controllerclientimpl.cpp +++ b/src/controllerclientimpl.cpp @@ -600,6 +600,14 @@ int ControllerClientImpl::_CallGet(const std::string& desturi, std::string& outp return http_code; } +int ControllerClientImpl::_DuplicateStreamCallback(char *data, size_t size, size_t nmemb, void **writerDataStringStreamAndOStream) +{ + if(((std::stringstream*)writerDataStringStreamAndOStream[0])->tellp() < 0x1000) { + ControllerClientImpl::_WriteStringStreamCallback(data, size, nmemb, (std::stringstream*)writerDataStringStreamAndOStream[0]); + } + return ControllerClientImpl::_WriteOStreamCallback(data, size, nmemb, (std::ostream*)writerDataStringStreamAndOStream[1]); +} + int ControllerClientImpl::CallGet(const std::string& relativeuri, std::ostream& outputStream, int expectedhttpcode, double timeout) { boost::mutex::scoped_lock lock(_mutex); @@ -614,15 +622,25 @@ int ControllerClientImpl::_CallGet(const std::string& desturi, std::ostream& out CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_TIMEOUT_MS, 0L, (long)(timeout * 1000L)); CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_HTTPHEADER, NULL, _httpheadersjson); CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_URL, NULL, desturi.c_str()); - CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_WRITEFUNCTION, NULL, _WriteOStreamCallback); - CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_WRITEDATA, NULL, &outputStream); + _buffer.clear(); + _buffer.str(""); + CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_WRITEFUNCTION, NULL, _DuplicateStreamCallback); + void *writerData[]={&_buffer,&outputStream}; + CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_WRITEDATA, NULL, writerData); CURL_OPTION_SAVE_SETTER(_curl, CURLOPT_HTTPGET, 0L, 1L); CURL_PERFORM(_curl); long http_code = 0; CURL_INFO_GETTER(_curl, CURLINFO_RESPONSE_CODE, &http_code); + std::string outputdata = _buffer.str(); if( expectedhttpcode != 0 && http_code != expectedhttpcode ) { - // outputStream is not always seekable; ignore any error message. - throw MUJIN_EXCEPTION_FORMAT("HTTP GET to '%s' returned HTTP status %s (outputStream might have information)", desturi%http_code, MEC_HTTPServer); + if( outputdata.size() > 0 ) { + rapidjson::Document d; + ParseJson(d, _buffer.str()); + std::string error_message = GetJsonValueByKey(d, "error_message"); + std::string traceback = GetJsonValueByKey(d, "traceback"); + throw MUJIN_EXCEPTION_FORMAT("HTTP GET to '%s' returned HTTP status %s: %s", desturi%http_code%error_message, MEC_HTTPServer); + } + throw MUJIN_EXCEPTION_FORMAT("HTTP GET to '%s' returned HTTP status %s", desturi%http_code, MEC_HTTPServer); } return http_code; } diff --git a/src/controllerclientimpl.h b/src/controllerclientimpl.h index 393055d3..f08672c3 100644 --- a/src/controllerclientimpl.h +++ b/src/controllerclientimpl.h @@ -181,6 +181,7 @@ class ControllerClientImpl : public ControllerClient, public boost::enable_share static int _WriteVectorCallback(char *data, size_t size, size_t nmemb, std::vector *writerData); static int _WriteOStreamCallback(char *data, size_t size, size_t nmemb, std::ostream *writerData); static int _ReadIStreamCallback(char *data, size_t size, size_t nmemb, std::istream *writerData); + static int _DuplicateStreamCallback(char *data, size_t size, size_t nmemb, void **writerDataStringStreamAndOStream); /// \brief sets up http header for doing http operation with json data void _SetupHTTPHeadersJSON();