RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* http_rest_proxy.cc 00002 Jeremy Barnes, 10 April 2013 00003 Copyright (c) 2013 Datacratic Inc. All rights reserved. 00004 00005 REST proxy class for http. 00006 */ 00007 00008 #include "http_rest_proxy.h" 00009 00010 #include <curlpp/cURLpp.hpp> 00011 #include <curlpp/Easy.hpp> 00012 #include <curlpp/Options.hpp> 00013 #include <curlpp/Info.hpp> 00014 #include <curlpp/Infos.hpp> 00015 00016 00017 using namespace std; 00018 using namespace ML; 00019 00020 00021 namespace Datacratic { 00022 00023 00024 /*****************************************************************************/ 00025 /* HTTP REST PROXY */ 00026 /*****************************************************************************/ 00027 00028 HttpRestProxy::Response 00029 HttpRestProxy:: 00030 perform(const std::string & verb, 00031 const std::string & resource, 00032 const Content & content, 00033 const RestParams & queryParams, 00034 const RestParams & headers, 00035 int timeout) const 00036 { 00037 string responseHeaders; 00038 string body; 00039 00040 try { 00041 responseHeaders.clear(); 00042 body.clear(); 00043 00044 curlpp::Easy myRequest; 00045 00046 using namespace curlpp::options; 00047 using namespace curlpp::infos; 00048 00049 list<string> curlHeaders; 00050 for (unsigned i = 0; i < headers.size(); ++i) { 00051 curlHeaders.push_back(headers[i].first + ": " 00052 + headers[i].second); 00053 } 00054 00055 std::string uri = serviceUri + resource + queryParams.uriEscaped(); 00056 00057 //cerr << "uri = " << uri << endl; 00058 00059 myRequest.setOpt<CustomRequest>(verb); 00060 00061 myRequest.setOpt<curlpp::options::Url>(uri); 00062 //myRequest.setOpt<Verbose>(true); 00063 myRequest.setOpt<ErrorBuffer>((char *)0); 00064 if (timeout != -1) 00065 myRequest.setOpt<Timeout>(timeout); 00066 myRequest.setOpt<NoSignal>(1); 00067 00068 auto onData = [&] (char * data, size_t ofs1, size_t ofs2) -> size_t 00069 { 00070 //cerr << "called onData for " << ofs1 << " " << ofs2 << endl; 00071 return 0; 00072 }; 00073 00074 auto onWriteData = [&] (char * data, size_t ofs1, size_t ofs2) -> size_t 00075 { 00076 body.append(data, ofs1 * ofs2); 00077 return ofs1 * ofs2; 00078 //cerr << "called onWrite for " << ofs1 << " " << ofs2 << endl; 00079 return 0; 00080 }; 00081 00082 auto onProgress = [&] (double p1, double p2, double p3, double p4) -> int 00083 { 00084 cerr << "progress " << p1 << " " << p2 << " " << p3 << " " 00085 << p4 << endl; 00086 return 0; 00087 }; 00088 00089 bool afterContinue = false; 00090 00091 auto onHeader = [&] (char * data, size_t ofs1, size_t ofs2) -> size_t 00092 { 00093 string headerLine(data, ofs1 * ofs2); 00094 if (headerLine.find("HTTP/1.1 100 Continue") == 0) { 00095 afterContinue = true; 00096 } 00097 else if (afterContinue) { 00098 if (headerLine == "\r\n") 00099 afterContinue = false; 00100 } 00101 else { 00102 responseHeaders.append(headerLine); 00103 //cerr << "got header data " << headerLine << endl; 00104 } 00105 return ofs1 * ofs2; 00106 }; 00107 00108 myRequest.setOpt<BoostHeaderFunction>(onHeader); 00109 myRequest.setOpt<BoostWriteFunction>(onWriteData); 00110 myRequest.setOpt<BoostProgressFunction>(onProgress); 00111 //myRequest.setOpt<Header>(true); 00112 00113 if (content.data) { 00114 string s(content.data, content.size); 00115 myRequest.setOpt<PostFields>(s); 00116 myRequest.setOpt<PostFieldSize>(content.size); 00117 curlHeaders.push_back(ML::format("Content-Length: %lld", 00118 content.size)); 00119 //curlHeaders.push_back("Transfer-Encoding:"); 00120 curlHeaders.push_back("Content-Type: " + content.contentType); 00121 } 00122 00123 myRequest.setOpt<curlpp::options::HttpHeader>(curlHeaders); 00124 00125 myRequest.perform(); 00126 00127 Response response; 00128 response.body_ = body; 00129 00130 curlpp::InfoGetter::get(myRequest, CURLINFO_RESPONSE_CODE, 00131 response.code_); 00132 00133 double bytesUploaded; 00134 00135 curlpp::InfoGetter::get(myRequest, CURLINFO_SIZE_UPLOAD, 00136 bytesUploaded); 00137 00138 //cerr << "uploaded " << bytesUploaded << " bytes" << endl; 00139 00140 response.header_.parse(responseHeaders); 00141 00142 return response; 00143 } catch (const curlpp::LibcurlRuntimeError & exc) { 00144 cerr << "libCurl returned an error with code " << exc.whatCode() 00145 << endl; 00146 cerr << "error is " << curl_easy_strerror(exc.whatCode()) 00147 << endl; 00148 //cerr << "uri is " << uri << endl; 00149 cerr << "headers are " << responseHeaders << endl; 00150 cerr << "body contains " << body.size() << " bytes" << endl; 00151 throw; 00152 } 00153 } 00154 00155 } // namespace Datacratic