RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* json_feeder.cc 00002 Wolfgang Sourdeau, February 2013 00003 Copyright (c) 2013 Datacratic. All rights reserved. 00004 00005 A utility that feeds a stream of JSON samples to an HTTP server. 00006 */ 00007 00008 00009 #include <string> 00010 00011 #include <boost/program_options/cmdline.hpp> 00012 #include <boost/program_options/options_description.hpp> 00013 #include <boost/program_options/positional_options.hpp> 00014 #include <boost/program_options/parsers.hpp> 00015 #include <boost/program_options/variables_map.hpp> 00016 00017 #include <curlpp/Easy.hpp> 00018 #include <curlpp/Info.hpp> 00019 #include <curlpp/Infos.hpp> 00020 #include <curlpp/Options.hpp> 00021 00022 #include "jml/utils/filter_streams.h" 00023 00024 00025 using namespace std; 00026 using namespace boost::program_options; 00027 using namespace curlpp; 00028 00029 00030 struct JsonFeeder { 00031 JsonFeeder(string uri, string filename, 00032 bool printRequests, bool printResponses, 00033 int maxSamples = 1000) 00034 : serverUri(uri), filename(filename), jsonStream(filename), 00035 printRequests(printRequests), printResponses(printResponses), 00036 maxSamples(maxSamples) 00037 {} 00038 00039 void perform() 00040 { 00041 int sampleNum; 00042 00043 for (sampleNum = 0; jsonStream && sampleNum < maxSamples; 00044 sampleNum++) { 00045 string current; 00046 getline(jsonStream, current); 00047 00048 if (current == "") { 00049 jsonStream = ML::filter_istream(filename); 00050 getline(jsonStream, current); 00051 } 00052 00053 Easy client; 00054 00055 /* perform request */ 00056 client.setOpt(options::Url(serverUri)); 00057 00058 client.setOpt(options::Post(true)); 00059 client.setOpt(options::PostFields(current)); 00060 00061 list<string> headers; 00062 headers.push_back("Content-Type: application/json"); 00063 headers.push_back("Expect:"); /* avoid dual-phase post */ 00064 client.setOpt(options::HttpHeader(headers)); 00065 00066 /* separate response headers from body and store response body in "body" */ 00067 stringstream body; 00068 client.setOpt(options::TcpNoDelay(true)); 00069 client.setOpt(options::Header(false)); 00070 client.setOpt(options::WriteStream(&body)); 00071 client.perform(); 00072 00073 if (sampleNum > 0 && (printRequests || printResponses)) { 00074 cerr << "----------------------------" << endl 00075 << "sample: " << sampleNum << endl; 00076 } 00077 00078 if (printRequests) { 00079 cerr << "rq body: " << current << endl; 00080 } 00081 00082 if (printResponses) { 00083 int code = infos::ResponseCode::get(client); 00084 cerr << "resp. code: " << code << endl 00085 << "resp. body: " << body.str() << endl; 00086 } 00087 } 00088 00089 cerr << "posted " << sampleNum << " samples" << endl; 00090 } 00091 00092 string serverUri; 00093 string filename; 00094 ML::filter_istream jsonStream; 00095 bool printRequests; 00096 bool printResponses; 00097 int maxSamples; 00098 }; 00099 00100 00101 int main(int argc, char *argv[]) 00102 { 00103 string serverUri; 00104 string filename; 00105 bool printRequests(false), printResponses(false); 00106 00107 { 00108 using namespace boost::program_options; 00109 00110 options_description configuration_options("Configuration options"); 00111 00112 configuration_options.add_options() 00113 ("server-uri,s", value(&serverUri), 00114 "URI of server to feed") 00115 ("filename,f", value(&filename), 00116 "filename") 00117 ("printrequests", value(&printRequests)->zero_tokens(), 00118 "print requests on console") 00119 ("printresponses", value(&printResponses)->zero_tokens(), 00120 "print responses on console"); 00121 00122 options_description all_opt; 00123 all_opt.add(configuration_options); 00124 all_opt.add_options() 00125 ("help,h", "print this message"); 00126 00127 variables_map vm; 00128 store(command_line_parser(argc, argv) 00129 .options(all_opt) 00130 .run(), 00131 vm); 00132 notify(vm); 00133 00134 if (vm.count("help")) { 00135 cerr << all_opt << endl; 00136 exit(1); 00137 } 00138 00139 if (serverUri.empty()) { 00140 cerr << "'server-uri' parameter is required" << endl; 00141 exit(1); 00142 } 00143 00144 if (filename.empty()) { 00145 cerr << "'filename' parameter is required" << endl; 00146 exit(1); 00147 } 00148 } 00149 00150 JsonFeeder feeder(serverUri, filename, printRequests, printResponses); 00151 feeder.perform(); 00152 00153 return 0; 00154 }