]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/webserver.hh
rec: ensure correct service user on debian
[thirdparty/pdns.git] / pdns / webserver.hh
index a147b254c0c954a5afd2cb9abede403d787f4364..d7848847f3aab4dc75ab8a4c8f3d2af247b0bd14 100644 (file)
@@ -34,11 +34,12 @@ class WebServer;
 
 class HttpRequest : public YaHTTP::Request {
 public:
-  HttpRequest() : YaHTTP::Request(), accept_json(false), accept_html(false), complete(false) { };
+  HttpRequest(const string& logprefix="") : YaHTTP::Request(), accept_json(false), accept_html(false), complete(false), logprefix(logprefix) { };
 
   bool accept_json;
   bool accept_html;
   bool complete;
+  string logprefix;
   json11::Json json();
 
   // checks password _only_.
@@ -65,6 +66,11 @@ public:
     d_response.status = status;
   };
 
+  HttpException(int status, const string& msg) : d_response()
+  {
+    d_response.setErrorResult(msg, status);
+  };
+
   HttpResponse response()
   {
     return d_response;
@@ -77,6 +83,7 @@ protected:
 class HttpBadRequestException : public HttpException {
 public:
   HttpBadRequestException() : HttpException(400) { };
+  HttpBadRequestException(const string& msg) : HttpException(400, msg) { };
 };
 
 class HttpUnauthorizedException : public HttpException {
@@ -90,26 +97,31 @@ public:
 class HttpForbiddenException : public HttpException {
 public:
   HttpForbiddenException() : HttpException(403) { };
+  HttpForbiddenException(const string& msg) : HttpException(403, msg) { };
 };
 
 class HttpNotFoundException : public HttpException {
 public:
   HttpNotFoundException() : HttpException(404) { };
+  HttpNotFoundException(const string& msg) : HttpException(404, msg) { };
 };
 
 class HttpMethodNotAllowedException : public HttpException {
 public:
   HttpMethodNotAllowedException() : HttpException(405) { };
+  HttpMethodNotAllowedException(const string& msg) : HttpException(405, msg) { };
 };
 
 class HttpConflictException : public HttpException {
 public:
   HttpConflictException() : HttpException(409) { };
+  HttpConflictException(const string& msg) : HttpException(409, msg) { };
 };
 
 class HttpInternalServerErrorException : public HttpException {
 public:
   HttpInternalServerErrorException() : HttpException(500) { };
+  HttpInternalServerErrorException(const string& msg) : HttpException(500, msg) { };
 };
 
 class ApiException : public runtime_error
@@ -146,16 +158,10 @@ public:
   virtual ~WebServer() { };
 
   void setApiKey(const string &apikey) {
-    if (d_registerApiHandlerCalled) {
-      throw PDNSException("registerApiHandler has been called, can not change apikey");
-    }
     d_apikey = apikey;
   }
 
   void setPassword(const string &password) {
-    if (d_registerWebHandlerCalled) {
-      throw PDNSException("registerWebHandler has been called, can not change password");
-    }
     d_webserverPassword = password;
   }
 
@@ -170,11 +176,46 @@ public:
   void handleRequest(HttpRequest& request, HttpResponse& resp) const;
 
   typedef boost::function<void(HttpRequest* req, HttpResponse* resp)> HandlerFunction;
-  void registerApiHandler(const string& url, HandlerFunction handler);
+  void registerApiHandler(const string& url, HandlerFunction handler, bool allowPassword=false);
   void registerWebHandler(const string& url, HandlerFunction handler);
 
+  enum class LogLevel : uint8_t {
+    None = 0,                // No logs from requests at all
+    Normal = 10,             // A "common log format"-like line e.g. '127.0.0.1 "GET /apache_pb.gif HTTP/1.0" 200 2326'
+    Detailed = 20,           // The full request headers and body, and the full response headers and body
+  };
+
+  void setLogLevel(const string& level) {
+    if (level == "none") {
+      d_loglevel = LogLevel::None;
+      return;
+    }
+
+    if (level == "normal") {
+      d_loglevel = LogLevel::Normal;
+      return;
+    }
+
+    if (level == "detailed") {
+      d_loglevel = LogLevel::Detailed;
+      return;
+    }
+
+    throw PDNSException("Unknown webserver log level: " + level);
+  }
+
+  void setLogLevel(const LogLevel level) {
+    d_loglevel = level;
+  };
+
+  LogLevel getLogLevel() {
+    return d_loglevel;
+  };
+
 protected:
   void registerBareHandler(const string& url, HandlerFunction handler);
+  void logRequest(const HttpRequest& req, const ComboAddress& remote) const;
+  void logResponse(const HttpResponse& resp, const ComboAddress& remote, const string& logprefix) const;
 
   virtual std::shared_ptr<Server> createServer() {
     return std::make_shared<Server>(d_listenaddress, d_port);
@@ -186,12 +227,16 @@ protected:
   std::shared_ptr<Server> d_server;
 
   std::string d_apikey;
-  bool d_registerApiHandlerCalled{false};
-
+  void apiWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp, bool allowPassword);
   std::string d_webserverPassword;
-  bool d_registerWebHandlerCalled{false};
+  void webWrapper(WebServer::HandlerFunction handler, HttpRequest* req, HttpResponse* resp);
 
   NetmaskGroup d_acl;
+
+  const string d_logprefix = "[webserver] ";
+
+  // Describes the amount of logging the webserver does
+  WebServer::LogLevel d_loglevel{WebServer::LogLevel::Detailed};
 };
 
 #endif /* WEBSERVER_HH */