RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 00016 #pragma once 00017 00018 #include "soa/service//http_endpoint.h" 00019 #include "jml/arch/format.h" 00020 #include "soa/jsoncpp/value.h" 00021 00022 #include <boost/shared_ptr.hpp> 00023 #include <boost/make_shared.hpp> 00024 00025 00026 namespace Datacratic { 00027 00028 00029 /******************************************************************************/ 00030 /* HTTP MONITOR */ 00031 /******************************************************************************/ 00032 00037 template<typename Handler, typename Arg = void*> 00038 struct HttpMonitor : public HttpEndpoint 00039 { 00040 HttpMonitor(const std::string& name) 00041 : HttpEndpoint(name) 00042 {} 00043 00047 void start(int port, Arg a = Arg()) 00048 { 00049 arg = a; 00050 init(port, "0.0.0.0"); 00051 } 00052 00053 private: 00054 00055 Arg arg; 00056 00057 virtual std::shared_ptr<ConnectionHandler> 00058 makeNewHandler() 00059 { 00060 return std::make_shared<Handler>(name(), arg); 00061 } 00062 }; 00063 00064 00065 /******************************************************************************/ 00066 /* HTTP MONITOR HANDLER */ 00067 /******************************************************************************/ 00068 00078 template<typename Handler, typename Arg = void*> 00079 struct HttpMonitorHandler : 00080 public HttpConnectionHandler 00081 { 00082 HttpMonitorHandler(const std::string& name, Arg arg); 00083 00085 virtual void 00086 handleHttpPayload(const HttpHeader & header, const std::string & payload); 00087 00092 virtual void 00093 doGet(const std::string& resource) {} 00094 00099 virtual void 00100 doPost(const std::string& resource, const std::string& payload) {} 00101 00106 virtual void 00107 doDelete(const std::string& resource, const std::string& payload) {} 00108 00109 void sendResponse(const Json::Value & response); 00110 void sendErrorResponse(int code, const std::string & error); 00111 void sendErrorResponse(int code, const Json::Value & error); 00112 00113 Arg getArg() { return arg; } 00114 00115 const std::string & name() const { return name_; } 00116 00117 private: 00118 Arg arg; 00119 std::string name_; 00120 }; 00121 00122 00123 /******************************************************************************/ 00124 /* HTTP MONITOR HANDLER IMPL */ 00125 /******************************************************************************/ 00126 00127 template<typename Handler, typename Arg> 00128 HttpMonitorHandler<Handler, Arg>:: 00129 HttpMonitorHandler( 00130 const std::string& name, Arg arg) : 00131 HttpConnectionHandler(), 00132 arg(arg), 00133 name_(name) 00134 {} 00135 00136 template<typename Handler, typename arg> 00137 void 00138 HttpMonitorHandler<Handler, arg>:: 00139 handleHttpPayload(const HttpHeader & header, const std::string & payload) 00140 { 00141 try { 00142 if (header.verb == "GET") 00143 doGet(header.resource); 00144 00145 else if (header.verb == "POST") 00146 doPost(header.resource, payload); 00147 00148 else if (header.verb == "DELETE") 00149 doDelete(header.resource, payload); 00150 00151 else sendErrorResponse(404, "bad verb " + header.verb); 00152 } 00153 catch(const std::exception& ex) { 00154 Json::Value response; 00155 response["error"] = 00156 "exception processing request " 00157 + header.verb + " " + header.resource; 00158 00159 response["exception"] = ex.what(); 00160 sendErrorResponse(400, response); 00161 } 00162 catch(...) { 00163 Json::Value response; 00164 response["error"] = 00165 "exception processing request " 00166 + header.verb + " " + header.resource; 00167 00168 sendErrorResponse(400, response); 00169 } 00170 } 00171 00172 00173 template<typename Handler, typename arg> 00174 void 00175 HttpMonitorHandler<Handler, arg>:: 00176 sendErrorResponse(int code, const std::string & error) 00177 { 00178 Json::Value val; 00179 val["error"] = error; 00180 sendErrorResponse(code, val); 00181 } 00182 00183 template<typename Handler, typename arg> 00184 void 00185 HttpMonitorHandler<Handler, arg>:: 00186 sendErrorResponse(int code, const Json::Value & error) 00187 { 00188 std::string encodedError = error.toString(); 00189 send(ML::format("HTTP/1.1 %d Pants are on fire\r\n" 00190 "Content-Type: application/json\r\n" 00191 "Access-Control-Allow-Origin: *\r\n" 00192 "Content-Length: %zd\r\n" 00193 "\r\n" 00194 "%s", 00195 code, 00196 encodedError.length(), 00197 encodedError.c_str()), 00198 NEXT_CLOSE); 00199 } 00200 00201 template<typename Handler, typename Arg> 00202 void 00203 HttpMonitorHandler<Handler, Arg>:: 00204 sendResponse(const Json::Value & response) 00205 { 00206 std::string body = response.toStyledString(); 00207 00208 auto onSendFinished = [=] { 00209 this->transport().associateWhenHandlerFinished 00210 (std::make_shared<Handler>(this->name(), this->arg), 00211 "sendResponse"); 00212 }; 00213 00214 send(ML::format("HTTP/1.1 200 OK\r\n" 00215 "Content-Type: application/json\r\n" 00216 "Access-Control-Allow-Origin: *\r\n" 00217 "Content-Length: %zd\r\n" 00218 "Connection: Keep-Alive\r\n" 00219 "\r\n" 00220 "%s", 00221 body.length(), 00222 body.c_str()), 00223 NEXT_CONTINUE, 00224 onSendFinished); 00225 } 00226 00227 } // Datacratic