]> granicus.if.org Git - pdns/commitdiff
webserver: first batch of new API URLs
authorChristian Hofstaedtler <christian@hofstaedtler.name>
Sun, 20 Oct 2013 16:34:44 +0000 (18:34 +0200)
committerChristian Hofstaedtler <christian@hofstaedtler.name>
Tue, 5 Nov 2013 09:53:15 +0000 (10:53 +0100)
Note that return data is still in old format.

pdns/json.cc
pdns/json.hh
pdns/json_ws.cc
pdns/ws.cc
pdns/ws.hh

index 59e44386aebcf50129547c050774222b22cde28e..c2132e1a01f902b18cdd67ecf000aa03569cef1f 100644 (file)
@@ -85,7 +85,7 @@ string returnJSONError(const string& error)
   return makeStringFromDocument(doc);
 }
 
-string makeLogGrepJSON(map<string, string>& varmap, const string& fname, const string& prefix)
+string makeLogGrepJSON(const string& q, const string& fname, const string& prefix)
 {
   FILE* ptr = fopen(fname.c_str(), "r");
   if(!ptr) {
@@ -94,7 +94,7 @@ string makeLogGrepJSON(map<string, string>& varmap, const string& fname, const s
   boost::shared_ptr<FILE> fp(ptr, fclose);
 
   string line;
-  string needle=varmap["needle"];
+  string needle = q;
   trim_right(needle);
 
   boost::replace_all(needle, "%20", " ");  
index 11a5742454703287ac4d3046efdc16d9b1dffcab..3945b05c5bca053a26c05bff55a4603af872ea3c 100644 (file)
@@ -27,5 +27,5 @@
 
 std::string returnJSONObject(const std::map<std::string, std::string>& items);
 std::string returnJSONError(const std::string& error);
-std::string makeLogGrepJSON(std::map<std::string, std::string>& varmap, const std::string& fname, const std::string& prefix="");
+std::string makeLogGrepJSON(const std::string& q, const std::string& fname, const std::string& prefix="");
 std::string makeStringFromDocument(const rapidjson::Document& doc);
index 53397e5f2517fd1cd270057f7c2a7cafbe6e16f1..d51fbb6b6951e8a68a9afb8081729785219e1a94 100644 (file)
@@ -225,7 +225,7 @@ string JWebserver::handleRequest(const string &method, const string &uri, const
     content += returnJSONObject(stats);  
   }
   else if(command == "log-grep") {
-    content += makeLogGrepJSON(varmap, ::arg()["experimental-logfile"], " pdns_recursor[");
+    content += makeLogGrepJSON(varmap["needle"], ::arg()["experimental-logfile"], " pdns_recursor[");
   }
   else { //  if(command == "stats") {
     stats = getAllStatsMap();
index 2758a7cbaa5a76f9a1c011be1ad3bb307f7c9f35..ccf141a2faee5347a38f80a060f664c5d638342f 100644 (file)
@@ -366,6 +366,72 @@ static string createOrUpdateZone(const string& zonename, bool onlyCreate, varmap
   return getZone(zonename);
 }
 
+static string apiServerConfig(HttpRequest* req) {
+  if(req->method != "GET")
+    throw HttpMethodNotAllowedException();
+
+  vector<string> items = ::arg().list();
+  Document doc;
+  doc.SetArray();
+  BOOST_FOREACH(const string& var, items) {
+    Value kv, key, value;
+    kv.SetArray();
+    key.SetString(var.c_str(), var.length());
+    kv.PushBack(key, doc.GetAllocator());
+
+    if(var.find("password") != string::npos)
+      value="*****";
+    else
+      value.SetString(::arg()[var].c_str(), ::arg()[var].length(), doc.GetAllocator());
+
+    kv.PushBack(value, doc.GetAllocator());
+    doc.PushBack(kv, doc.GetAllocator());
+  }
+  return makeStringFromDocument(doc);
+}
+
+static string apiServerSearchLog(HttpRequest* req) {
+  if(req->method != "GET")
+    throw HttpMethodNotAllowedException();
+
+  return makeLogGrepJSON(req->queryArgs["q"], ::arg()["experimental-logfile"], " pdns[");
+}
+
+static string apiServerZones(HttpRequest* req) {
+  if(req->method != "GET")
+    throw HttpMethodNotAllowedException();
+
+  UeberBackend B;
+  vector<DomainInfo> domains;
+  B.getAllDomains(&domains);
+
+  Document doc;
+  doc.SetObject();
+
+  Value jdomains;
+  jdomains.SetArray();
+
+  BOOST_FOREACH(const DomainInfo& di, domains) {
+    Value jdi;
+    jdi.SetObject();
+    jdi.AddMember("name", di.zone.c_str(), doc.GetAllocator());
+    jdi.AddMember("kind", di.getKindString(), doc.GetAllocator());
+    Value masters;
+    masters.SetArray();
+    BOOST_FOREACH(const string& master, di.masters) {
+      Value value(master.c_str(), doc.GetAllocator());
+      masters.PushBack(value, doc.GetAllocator());
+    }
+    jdi.AddMember("masters", masters, doc.GetAllocator());
+    jdi.AddMember("serial", di.serial, doc.GetAllocator());
+    jdi.AddMember("notified_serial", di.notified_serial, doc.GetAllocator());
+    jdi.AddMember("last_check", (unsigned int) di.last_check, doc.GetAllocator());
+    jdomains.PushBack(jdi, doc.GetAllocator());
+  }
+  doc.AddMember("domains", jdomains, doc.GetAllocator());
+  return makeStringFromDocument(doc);
+}
+
 static string jsonDispatch(HttpRequest* req, const string& command) {
   if(command=="get") {
     if(req->queryArgs.empty()) {
@@ -398,24 +464,7 @@ static string jsonDispatch(HttpRequest* req, const string& command) {
     return makeStringFromDocument(doc);
   }
   else if(command=="config") {
-    vector<string> items = ::arg().list();
-    Document doc;
-    doc.SetArray();
-    BOOST_FOREACH(const string& var, items) {
-      Value kv, key, value;
-      kv.SetArray();
-      key.SetString(var.c_str(), var.length());
-      kv.PushBack(key, doc.GetAllocator());
-      
-      if(var.find("password") != string::npos)
-        value="*****";
-      else 
-        value.SetString(::arg()[var].c_str(), ::arg()[var].length(), doc.GetAllocator());
-      
-      kv.PushBack(value, doc.GetAllocator());
-      doc.PushBack(kv, doc.GetAllocator());
-    }
-    return makeStringFromDocument(doc);
+    return apiServerConfig(req);
   }
   else if(command == "flush-cache") {
     extern PacketCache PC;
@@ -565,45 +614,16 @@ static string jsonDispatch(HttpRequest* req, const string& command) {
     }
   }
   else if(command=="log-grep") {
-    return makeLogGrepJSON(req->queryArgs, ::arg()["experimental-logfile"], " pdns[");
+    return makeLogGrepJSON(req->queryArgs["needle"], ::arg()["experimental-logfile"], " pdns[");
   }
   else if(command=="domains") {
-    UeberBackend B;
-    vector<DomainInfo> domains;
-    B.getAllDomains(&domains);
-    
-    Document doc;
-    doc.SetObject();
-    
-    Value jdomains;
-    jdomains.SetArray();
-    
-    BOOST_FOREACH(const DomainInfo& di, domains) {
-      Value jdi;
-      jdi.SetObject();
-      jdi.AddMember("name", di.zone.c_str(), doc.GetAllocator());
-      jdi.AddMember("kind", di.getKindString(), doc.GetAllocator());
-      Value masters;
-      masters.SetArray();
-      BOOST_FOREACH(const string& master, di.masters) {
-        Value value(master.c_str(), doc.GetAllocator());
-        masters.PushBack(value, doc.GetAllocator());
-      }
-      jdi.AddMember("masters", masters, doc.GetAllocator());
-      jdi.AddMember("serial", di.serial, doc.GetAllocator());
-      jdi.AddMember("notified_serial", di.notified_serial, doc.GetAllocator());
-      jdi.AddMember("last_check", (unsigned int) di.last_check, doc.GetAllocator());
-      jdomains.PushBack(jdi, doc.GetAllocator());
-    }
-    doc.AddMember("domains", jdomains, doc.GetAllocator());
-    return makeStringFromDocument(doc);
+    return apiServerZones(req);
   }
 
   return returnJSONError("No or unknown command given");
 }
 
-string StatWebServer::jsonstat(HttpRequest* req, bool *custom)
-{
+static string apiWrapper(boost::function<string(HttpRequest*)> handler, HttpRequest* req, bool *custom) {
   *custom=1; // indicates we build the response
   string ret="HTTP/1.1 200 OK\r\n"
   "Server: PowerDNS/"VERSION"\r\n"
@@ -613,23 +633,18 @@ string StatWebServer::jsonstat(HttpRequest* req, bool *custom)
   "\r\n" ;
 
   string callback;
-  string command;
 
   if(req->queryArgs.count("callback")) {
     callback=req->queryArgs["callback"];
     req->queryArgs.erase("callback");
   }
   
-  if(req->queryArgs.count("command")) {
-    command=req->queryArgs["command"];
-    req->queryArgs.erase("command");
-  }
+  req->queryArgs.erase("_"); // jQuery cache buster
 
-  req->queryArgs.erase("_");
   if(!callback.empty())
       ret += callback+"(";
 
-  ret += jsonDispatch(req, command);
+  ret += handler(req);
 
   if(!callback.empty()) {
     ret += ");";
@@ -637,6 +652,23 @@ string StatWebServer::jsonstat(HttpRequest* req, bool *custom)
   return ret;
 }
 
+void StatWebServer::registerApiHandler(const string& url, boost::function<string(HttpRequest*)> handler) {
+  WebServer::HandlerFunction f = boost::bind(&apiWrapper, handler, _1, _2);
+  d_ws->registerHandler(url, f);
+}
+
+string StatWebServer::jsonstat(HttpRequest* req)
+{
+  string command;
+
+  if(req->queryArgs.count("command")) {
+    command=req->queryArgs["command"];
+    req->queryArgs.erase("command");
+  }
+
+  return jsonDispatch(req, command);
+}
+
 string StatWebServer::cssfunction(HttpRequest* req, bool *custom)
 {
   *custom=1; // indicates we build the response
@@ -682,8 +714,13 @@ void StatWebServer::launch()
   try {
     d_ws->registerHandler("/", boost::bind(&StatWebServer::indexfunction, this, _1, _2));
     d_ws->registerHandler("/style.css", boost::bind(&StatWebServer::cssfunction, this, _1, _2));
-    if(::arg().mustDo("experimental-json-interface"))
-      d_ws->registerHandler("/jsonstat", boost::bind(&StatWebServer::jsonstat, this, _1, _2));
+    if(::arg().mustDo("experimental-json-interface")) {
+      registerApiHandler("/servers/localhost/config", &apiServerConfig);
+      registerApiHandler("/servers/localhost/search-log", &apiServerSearchLog);
+      registerApiHandler("/servers/localhost/zones", &apiServerZones);
+      // legacy dispatch
+      registerApiHandler("/jsonstat", boost::bind(&StatWebServer::jsonstat, this, _1));
+    }
     d_ws->go();
   }
   catch(...) {
index d01f965de86af0339efd7a711127d17abd0c9684..85ae9757022521ccb48c16ffd85a5ab347efe39d 100644 (file)
@@ -84,12 +84,14 @@ public:
   StatWebServer();
   void go();
   static string makePercentage(const double& val);
+
 private:
   static void *threadHelper(void *);
   static void *statThreadHelper(void *p);
   string indexfunction(HttpRequest* req, bool *custom);
   string cssfunction(HttpRequest* req, bool *custom);
-  string jsonstat(HttpRequest* req, bool *custom);
+  string jsonstat(HttpRequest* req);
+  void registerApiHandler(const string& url, boost::function<string(HttpRequest*)> handler);
   void printvars(ostringstream &ret);
   void printargs(ostringstream &ret);
   void launch();