RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/service/http_monitor.h
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator