Hide ProtocolHandler implementation

Move ProtocolHandler implementation and fields into DBusProtocolHandler
and extract a ProtocolHandler interface.

Bug: 25932908
Test: `mmma -j16 system/webservd`

Change-Id: I9100387f331e899da9bf44202ce2becf5fad4895
diff --git a/libwebserv/Android.mk b/libwebserv/Android.mk
index 50235bc..bffcd7a 100644
--- a/libwebserv/Android.mk
+++ b/libwebserv/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SHARED_LIBRARIES := libwebservd-client-internal
 LOCAL_SRC_FILES := \
     dbus_bindings/org.chromium.WebServer.RequestHandler.dbus-xml \
+    dbus_protocol_handler.cc \
     dbus_server.cc \
     protocol_handler.cc \
     request.cc \
diff --git a/libwebserv/dbus_protocol_handler.cc b/libwebserv/dbus_protocol_handler.cc
new file mode 100644
index 0000000..ff7e8b9
--- /dev/null
+++ b/libwebserv/dbus_protocol_handler.cc
@@ -0,0 +1,318 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "libwebserv/dbus_protocol_handler.h"
+
+#include <tuple>
+
+#include <base/logging.h>
+#include <brillo/map_utils.h>
+#include <brillo/streams/file_stream.h>
+#include <brillo/streams/stream_utils.h>
+
+#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
+#include "libwebserv/dbus_server.h"
+#include "libwebserv/protocol_handler.h"
+#include "libwebserv/request.h"
+#include "libwebserv/request_handler_callback.h"
+#include "libwebserv/response_impl.h"
+#include "webservd/dbus-proxies.h"
+
+namespace libwebserv {
+
+namespace {
+
+// Dummy callback for async D-Bus errors.
+void IgnoreDBusError(brillo::Error* error) {}
+
+// Copies the data from |src_stream| to the destination stream represented
+// by a file descriptor |fd|.
+void WriteResponseData(brillo::StreamPtr src_stream,
+                       const dbus::FileDescriptor& fd) {
+  int dupfd = dup(fd.value());
+  auto dest_stream =
+      brillo::FileStream::FromFileDescriptor(dupfd, true, nullptr);
+  CHECK(dest_stream);
+  // Dummy callbacks for success/error of data-copy operation. We ignore both
+  // notifications here.
+  auto on_success = [](brillo::StreamPtr, brillo::StreamPtr, uint64_t) {};
+  auto on_error = [](brillo::StreamPtr, brillo::StreamPtr,
+                     const brillo::Error*) {};
+  brillo::stream_utils::CopyData(
+      std::move(src_stream), std::move(dest_stream), base::Bind(on_success),
+      base::Bind(on_error));
+}
+
+}  // anonymous namespace
+
+DBusProtocolHandler::DBusProtocolHandler(const std::string& name,
+                                         DBusServer* server)
+    : name_{name}, server_{server} {
+}
+
+DBusProtocolHandler::~DBusProtocolHandler() {
+  // Remove any existing handlers, so the web server knows that we don't
+  // need them anymore.
+
+  // We need to get a copy of the map keys since removing the handlers will
+  // modify the map in the middle of the loop and that's not a good thing.
+  auto handler_ids = brillo::GetMapKeys(request_handlers_);
+  for (int handler_id : handler_ids) {
+    RemoveHandler(handler_id);
+  }
+}
+bool DBusProtocolHandler::IsConnected() const {
+  return !proxies_.empty();
+}
+
+std::string DBusProtocolHandler::GetName() const {
+  return name_;
+}
+
+std::set<uint16_t> DBusProtocolHandler::GetPorts() const {
+  std::set<uint16_t> ports;
+  for (const auto& pair : proxies_)
+    ports.insert(pair.second->port());
+  return ports;
+}
+
+std::set<std::string> DBusProtocolHandler::GetProtocols() const {
+  std::set<std::string> protocols;
+  for (const auto& pair : proxies_)
+    protocols.insert(pair.second->protocol());
+  return protocols;
+}
+
+brillo::Blob DBusProtocolHandler::GetCertificateFingerprint() const {
+  brillo::Blob fingerprint;
+  for (const auto& pair : proxies_) {
+    fingerprint = pair.second->certificate_fingerprint();
+    if (!fingerprint.empty())
+      break;
+  }
+  return fingerprint;
+}
+
+int DBusProtocolHandler::AddHandler(
+    const std::string& url,
+    const std::string& method,
+    std::unique_ptr<RequestHandlerInterface> handler) {
+  request_handlers_.emplace(
+      ++last_handler_id_,
+      HandlerMapEntry{url, method,
+                      std::map<ProtocolHandlerProxyInterface*, std::string>{},
+                      std::move(handler)});
+  // For each instance of remote protocol handler object sharing the same name,
+  // add the request handler.
+  for (const auto& pair : proxies_) {
+    pair.second->AddRequestHandlerAsync(
+        url,
+        method,
+        server_->service_name_,
+        base::Bind(&DBusProtocolHandler::AddHandlerSuccess,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   last_handler_id_,
+                   pair.second),
+        base::Bind(&DBusProtocolHandler::AddHandlerError,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   last_handler_id_));
+  }
+  return last_handler_id_;
+}
+
+int DBusProtocolHandler::AddHandlerCallback(
+    const std::string& url,
+    const std::string& method,
+    const base::Callback<RequestHandlerInterface::HandlerSignature>&
+        handler_callback) {
+  std::unique_ptr<RequestHandlerInterface> handler{
+      new RequestHandlerCallback{handler_callback}};
+  return AddHandler(url, method, std::move(handler));
+}
+
+bool DBusProtocolHandler::RemoveHandler(int handler_id) {
+  auto p = request_handlers_.find(handler_id);
+  if (p == request_handlers_.end())
+    return false;
+
+  for (const auto& pair : p->second.remote_handler_ids) {
+    pair.first->RemoveRequestHandlerAsync(
+        pair.second,
+        base::Bind(&base::DoNothing),
+        base::Bind(&IgnoreDBusError));
+  }
+
+  request_handlers_.erase(p);
+  return true;
+}
+
+void DBusProtocolHandler::Connect(ProtocolHandlerProxyInterface* proxy) {
+  proxies_.emplace(proxy->GetObjectPath(), proxy);
+  for (const auto& pair : request_handlers_) {
+    proxy->AddRequestHandlerAsync(
+        pair.second.url,
+        pair.second.method,
+        server_->service_name_,
+        base::Bind(&DBusProtocolHandler::AddHandlerSuccess,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   pair.first,
+                   proxy),
+        base::Bind(&DBusProtocolHandler::AddHandlerError,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   pair.first));
+  }
+}
+
+void DBusProtocolHandler::Disconnect(const dbus::ObjectPath& object_path) {
+  proxies_.erase(object_path);
+  if (proxies_.empty())
+    remote_handler_id_map_.clear();
+  for (auto& pair : request_handlers_)
+    pair.second.remote_handler_ids.clear();
+}
+
+void DBusProtocolHandler::AddHandlerSuccess(
+    int handler_id,
+    ProtocolHandlerProxyInterface* proxy,
+    const std::string& remote_handler_id) {
+  auto p = request_handlers_.find(handler_id);
+  CHECK(p != request_handlers_.end());
+  p->second.remote_handler_ids.emplace(proxy, remote_handler_id);
+
+  remote_handler_id_map_.emplace(remote_handler_id, handler_id);
+}
+
+void DBusProtocolHandler::AddHandlerError(int handler_id,
+                                          brillo::Error* error) {
+  // Nothing to do at the moment.
+}
+
+bool DBusProtocolHandler::ProcessRequest(const std::string& protocol_handler_id,
+                                     const std::string& remote_handler_id,
+                                     const std::string& request_id,
+                                     std::unique_ptr<Request> request,
+                                     brillo::ErrorPtr* error) {
+  request_id_map_.emplace(request_id, protocol_handler_id);
+  auto id_iter = remote_handler_id_map_.find(remote_handler_id);
+  if (id_iter == remote_handler_id_map_.end()) {
+    brillo::Error::AddToPrintf(error, FROM_HERE,
+                               brillo::errors::dbus::kDomain,
+                               DBUS_ERROR_FAILED,
+                               "Unknown request handler '%s'",
+                               remote_handler_id.c_str());
+    return false;
+  }
+  auto handler_iter = request_handlers_.find(id_iter->second);
+  if (handler_iter == request_handlers_.end()) {
+    brillo::Error::AddToPrintf(error, FROM_HERE,
+                               brillo::errors::dbus::kDomain,
+                               DBUS_ERROR_FAILED,
+                               "Handler # %d is no longer available",
+                               id_iter->second);
+    return false;
+  }
+  handler_iter->second.handler->HandleRequest(
+      std::move(request),
+      std::unique_ptr<Response>{new ResponseImpl{this, request_id}});
+  return true;
+}
+
+void DBusProtocolHandler::CompleteRequest(
+    const std::string& request_id,
+    int status_code,
+    const std::multimap<std::string, std::string>& headers,
+    brillo::StreamPtr data_stream) {
+  ProtocolHandlerProxyInterface* proxy =
+      GetRequestProtocolHandlerProxy(request_id);
+  if (!proxy)
+    return;
+
+  std::vector<std::tuple<std::string, std::string>> header_list;
+  header_list.reserve(headers.size());
+  for (const auto& pair : headers)
+    header_list.emplace_back(pair.first, pair.second);
+
+  int64_t data_size = -1;
+  if (data_stream->CanGetSize())
+    data_size = data_stream->GetRemainingSize();
+  proxy->CompleteRequestAsync(
+      request_id, status_code, header_list, data_size,
+      base::Bind(&WriteResponseData, base::Passed(&data_stream)),
+      base::Bind(&IgnoreDBusError));
+}
+
+void DBusProtocolHandler::GetFileData(
+    const std::string& request_id,
+    int file_id,
+    const base::Callback<void(brillo::StreamPtr)>& success_callback,
+    const base::Callback<void(brillo::Error*)>& error_callback) {
+  ProtocolHandlerProxyInterface* proxy =
+      GetRequestProtocolHandlerProxy(request_id);
+  CHECK(proxy);
+
+  // Store the success/error callback in a shared object so it can be referenced
+  // by the two wrapper callbacks. Since the original callbacks MAY contain
+  // move-only types, copying the base::Callback object is generally unsafe and
+  // may destroy the source object of the copy (despite the fact that it is
+  // constant). So, here we move both callbacks to |Callbacks| structure and
+  // use a shared pointer to it in both success and error callback wrappers.
+  struct Callbacks {
+    base::Callback<void(brillo::StreamPtr)> on_success;
+    base::Callback<void(brillo::Error*)> on_error;
+  };
+  auto callbacks = std::make_shared<Callbacks>();
+  callbacks->on_success = success_callback;
+  callbacks->on_error = error_callback;
+
+  auto on_success = [callbacks](const dbus::FileDescriptor& fd) {
+    brillo::ErrorPtr error;
+    // Unfortunately there is no way to take ownership of the file descriptor
+    // since |fd| is a const reference, so duplicate the descriptor.
+    int dupfd = dup(fd.value());
+    auto stream = brillo::FileStream::FromFileDescriptor(dupfd, true, &error);
+    if (!stream)
+      return callbacks->on_error.Run(error.get());
+    callbacks->on_success.Run(std::move(stream));
+  };
+  auto on_error = [callbacks](brillo::Error* error) {
+    callbacks->on_error.Run(error);
+  };
+
+  proxy->GetRequestFileDataAsync(request_id, file_id, base::Bind(on_success),
+                                 base::Bind(on_error));
+}
+
+DBusProtocolHandler::ProtocolHandlerProxyInterface*
+DBusProtocolHandler::GetRequestProtocolHandlerProxy(
+    const std::string& request_id) const {
+  auto iter = request_id_map_.find(request_id);
+  if (iter == request_id_map_.end()) {
+    LOG(ERROR) << "Can't find pending request with ID " << request_id;
+    return nullptr;
+  }
+  std::string handler_id = iter->second;
+  auto find_proxy_by_id = [handler_id](decltype(*proxies_.begin()) pair) {
+    return pair.second->id() == handler_id;
+  };
+  auto proxy_iter = std::find_if(proxies_.begin(), proxies_.end(),
+                                 find_proxy_by_id);
+  if (proxy_iter == proxies_.end()) {
+    LOG(WARNING) << "Completing a request after the handler proxy is removed";
+    return nullptr;
+  }
+  return proxy_iter->second;
+}
+
+
+}  // namespace libwebserv
diff --git a/libwebserv/dbus_protocol_handler.h b/libwebserv/dbus_protocol_handler.h
new file mode 100644
index 0000000..74e0b49
--- /dev/null
+++ b/libwebserv/dbus_protocol_handler.h
@@ -0,0 +1,164 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef WEBSERVER_LIBWEBSERV_DBUS_PROTOCOL_HANDLER_H_
+#define WEBSERVER_LIBWEBSERV_DBUS_PROTOCOL_HANDLER_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <base/callback_forward.h>
+#include <base/macros.h>
+#include <base/memory/weak_ptr.h>
+#include <brillo/errors/error.h>
+#include <brillo/secure_blob.h>
+#include <brillo/streams/stream.h>
+#include <dbus/object_path.h>
+
+#include <libwebserv/export.h>
+#include <libwebserv/protocol_handler.h>
+#include <libwebserv/request_handler_interface.h>
+
+namespace org {
+namespace chromium {
+namespace WebServer {
+
+class ProtocolHandlerProxyInterface;
+
+}  // namespace WebServer
+}  // namespace chromium
+}  // namespace org
+
+namespace libwebserv {
+
+class DBusServer;
+class Request;
+
+class LIBWEBSERV_PRIVATE DBusProtocolHandler : public ProtocolHandler {
+ public:
+  DBusProtocolHandler(const std::string& name, DBusServer* server);
+  ~DBusProtocolHandler() override;
+
+  bool IsConnected() const override;
+
+  std::string GetName() const override;
+
+  std::set<uint16_t> GetPorts() const override;
+
+  std::set<std::string> GetProtocols() const override;
+
+  brillo::Blob GetCertificateFingerprint() const override;
+
+  int AddHandler(const std::string& url,
+                 const std::string& method,
+                 std::unique_ptr<RequestHandlerInterface> handler) override;
+
+  int AddHandlerCallback(
+      const std::string& url,
+      const std::string& method,
+      const base::Callback<RequestHandlerInterface::HandlerSignature>&
+          handler_callback) override;
+
+  bool RemoveHandler(int handler_id) override;
+
+ private:
+  friend class FileInfo;
+  friend class DBusServer;
+  friend class ResponseImpl;
+
+  using ProtocolHandlerProxyInterface =
+      org::chromium::WebServer::ProtocolHandlerProxyInterface;
+
+  struct HandlerMapEntry {
+    std::string url;
+    std::string method;
+    std::map<ProtocolHandlerProxyInterface*, std::string> remote_handler_ids;
+    std::unique_ptr<RequestHandlerInterface> handler;
+  };
+
+  // Called by the DBusServer class when the D-Bus proxy object gets connected
+  // to the web server daemon.
+  void Connect(ProtocolHandlerProxyInterface* proxy);
+
+  // Called by the DBusServer class when the D-Bus proxy object gets
+  // disconnected from the web server daemon.
+  void Disconnect(const dbus::ObjectPath& object_path);
+
+  // Asynchronous callbacks to handle successful or failed request handler
+  // registration over D-Bus.
+  void AddHandlerSuccess(
+      int handler_id,
+      ProtocolHandlerProxyInterface* proxy,
+      const std::string& remote_handler_id);
+  void AddHandlerError(int handler_id, brillo::Error* error);
+
+  // Called by DBusServer when an incoming request is dispatched.
+  bool ProcessRequest(const std::string& protocol_handler_id,
+                      const std::string& remote_handler_id,
+                      const std::string& request_id,
+                      std::unique_ptr<Request> request,
+                      brillo::ErrorPtr* error);
+
+  // Called by Response object to finish the request and send response data.
+  void CompleteRequest(
+      const std::string& request_id,
+      int status_code,
+      const std::multimap<std::string, std::string>& headers,
+      brillo::StreamPtr data_stream);
+
+  // Makes a call to the (remote) web server request handler over D-Bus to
+  // obtain the file content of uploaded file (identified by |file_id|) during
+  // request with |request_id|.
+  void GetFileData(
+      const std::string& request_id,
+      int file_id,
+      const base::Callback<void(brillo::StreamPtr)>& success_callback,
+      const base::Callback<void(brillo::Error*)>& error_callback);
+
+  // A helper method to obtain a corresponding protocol handler D-Bus proxy for
+  // outstanding request with ID |request_id|.
+  ProtocolHandlerProxyInterface* GetRequestProtocolHandlerProxy(
+      const std::string& request_id) const;
+
+  // Protocol Handler name.
+  std::string name_;
+  // Back reference to the server object.
+  DBusServer* server_{nullptr};
+  // Handler data map. The key is the client-facing request handler ID returned
+  // by AddHandler() when registering the handler.
+  std::map<int, HandlerMapEntry> request_handlers_;
+  // The counter to generate new handler IDs.
+  int last_handler_id_{0};
+  // Map of remote handler IDs (GUID strings) to client-facing request handler
+  // IDs (int) which are returned by AddHandler() and used as a key in
+  // |request_handlers_|.
+  std::map<std::string, int> remote_handler_id_map_;
+  // Remote D-Bus proxies for the server protocol handler objects.
+  // There could be multiple protocol handlers with the same name (to make
+  // it possible to server the same requests on different ports, for example).
+  std::map<dbus::ObjectPath, ProtocolHandlerProxyInterface*> proxies_;
+  // A map of request ID to protocol handler ID. Used to locate the appropriate
+  // protocol handler D-Bus proxy for given request.
+  std::map<std::string, std::string> request_id_map_;
+
+  base::WeakPtrFactory<DBusProtocolHandler> weak_ptr_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(DBusProtocolHandler);
+};
+
+}  // namespace libwebserv
+
+#endif  // WEBSERVER_LIBWEBSERV_DBUS_PROTOCOL_HANDLER_H_
diff --git a/libwebserv/dbus_server.cc b/libwebserv/dbus_server.cc
index 091b02f..90ace2b 100644
--- a/libwebserv/dbus_server.cc
+++ b/libwebserv/dbus_server.cc
@@ -17,7 +17,7 @@
 #include <tuple>
 #include <vector>
 
-#include <libwebserv/protocol_handler.h>
+#include <libwebserv/dbus_protocol_handler.h>
 #include <libwebserv/request_impl.h>
 
 #include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
@@ -58,7 +58,7 @@
   std::string request_id = std::get<2>(in_request_info);
   std::string url = std::get<3>(in_request_info);
   std::string method = std::get<4>(in_request_info);
-  ProtocolHandler* protocol_handler =
+  DBusProtocolHandler* protocol_handler =
       server_->GetProtocolHandlerByID(protocol_handler_id);
   if (!protocol_handler) {
     brillo::Error::AddToPrintf(error, FROM_HERE,
@@ -169,7 +169,8 @@
           << "' is on-line (" << handler->name() << ")";
 
   protocol_handler_id_map_.emplace(handler->GetObjectPath(), handler->id());
-  ProtocolHandler* registered_handler = GetProtocolHandler(handler->name());
+  DBusProtocolHandler* registered_handler =
+      GetProtocolHandlerImpl(handler->name());
   if (registered_handler) {
     protocol_handlers_ids_.emplace(handler->id(), registered_handler);
     registered_handler->Connect(handler);
@@ -186,7 +187,7 @@
   VLOG(1) << "Server-side protocol handler with ID '" << p->second
           << "' is off-line.";
 
-  ProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
+  DBusProtocolHandler* registered_handler = GetProtocolHandlerByID(p->second);
   if (registered_handler) {
     if (!on_protocol_handler_disconnected_.is_null())
       on_protocol_handler_disconnected_.Run(registered_handler);
@@ -198,14 +199,19 @@
 }
 
 ProtocolHandler* DBusServer::GetProtocolHandler(const std::string& name) {
+  return GetProtocolHandlerImpl(name);
+}
+
+DBusProtocolHandler* DBusServer::GetProtocolHandlerImpl(
+    const std::string& name) {
   auto p = protocol_handlers_names_.find(name);
   if (p == protocol_handlers_names_.end()) {
     VLOG(1) << "Creating a client-side instance of web server's protocol "
             << "handler with name '" << name << "'";
     p = protocol_handlers_names_.emplace(
         name,
-        std::unique_ptr<ProtocolHandler>{new ProtocolHandler{name, this}})
-            .first;
+        std::unique_ptr<DBusProtocolHandler>{
+            new DBusProtocolHandler{name, this}}).first;
   }
   return p->second.get();
 }
@@ -218,7 +224,8 @@
   return GetProtocolHandler(ProtocolHandler::kHttps);
 }
 
-ProtocolHandler* DBusServer::GetProtocolHandlerByID(const std::string& id) const {
+DBusProtocolHandler* DBusServer::GetProtocolHandlerByID(
+    const std::string& id) const {
   auto p = protocol_handlers_ids_.find(id);
   if (p == protocol_handlers_ids_.end()) {
     LOG(ERROR) << "Unable to locate protocol handler with ID '" << id << "'";
diff --git a/libwebserv/dbus_server.h b/libwebserv/dbus_server.h
index 36bcdcb..dbfdbe2 100644
--- a/libwebserv/dbus_server.h
+++ b/libwebserv/dbus_server.h
@@ -43,6 +43,8 @@
 
 namespace libwebserv {
 
+class DBusProtocolHandler;
+
 class LIBWEBSERV_PRIVATE DBusServer : public Server {
  public:
   DBusServer();
@@ -79,7 +81,7 @@
   base::TimeDelta GetDefaultRequestTimeout() const override;
 
  private:
-  friend class ProtocolHandler;
+  friend class DBusProtocolHandler;
   class RequestHandler;
 
   void Disconnect();
@@ -100,9 +102,12 @@
       const dbus::ObjectPath& object_path);
 
   // Looks up a protocol handler by ID. If not found, returns nullptr.
-  ProtocolHandler* GetProtocolHandlerByID(
+  DBusProtocolHandler* GetProtocolHandlerByID(
       const std::string& id) const;
 
+  // Like the public version, but returns our specific handler type.
+  DBusProtocolHandler* GetProtocolHandlerImpl(const std::string& name);
+
   // Private implementation of D-Bus RequestHandlerInterface called by the web
   // server daemon whenever a new request is available to be processed.
   std::unique_ptr<RequestHandler> request_handler_;
@@ -113,10 +118,10 @@
   std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object_;
 
   // A mapping of protocol handler name to the associated object.
-  std::map<std::string, std::unique_ptr<ProtocolHandler>>
+  std::map<std::string, std::unique_ptr<DBusProtocolHandler>>
       protocol_handlers_names_;
   // A mapping of protocol handler IDs to the associated object.
-  std::map<std::string, ProtocolHandler*> protocol_handlers_ids_;
+  std::map<std::string, DBusProtocolHandler*> protocol_handlers_ids_;
   // A map between D-Bus object path of protocol handler and remote protocol
   // handler ID.
   std::map<dbus::ObjectPath, std::string> protocol_handler_id_map_;
diff --git a/libwebserv/protocol_handler.cc b/libwebserv/protocol_handler.cc
index 8c50d47..b4e54b4 100644
--- a/libwebserv/protocol_handler.cc
+++ b/libwebserv/protocol_handler.cc
@@ -12,303 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "libwebserv/protocol_handler.h"
-
-#include <tuple>
-
-#include <base/logging.h>
-#include <brillo/map_utils.h>
-#include <brillo/streams/file_stream.h>
-#include <brillo/streams/stream_utils.h>
-
-#include "dbus_bindings/org.chromium.WebServer.RequestHandler.h"
-#include "libwebserv/dbus_server.h"
-#include "libwebserv/request.h"
-#include "libwebserv/request_handler_callback.h"
-#include "libwebserv/response_impl.h"
-#include "webservd/dbus-proxies.h"
+#include <libwebserv/protocol_handler.h>
 
 namespace libwebserv {
 
-namespace {
-
-// Dummy callback for async D-Bus errors.
-void IgnoreDBusError(brillo::Error* error) {}
-
-// Copies the data from |src_stream| to the destination stream represented
-// by a file descriptor |fd|.
-void WriteResponseData(brillo::StreamPtr src_stream,
-                       const dbus::FileDescriptor& fd) {
-  int dupfd = dup(fd.value());
-  auto dest_stream =
-      brillo::FileStream::FromFileDescriptor(dupfd, true, nullptr);
-  CHECK(dest_stream);
-  // Dummy callbacks for success/error of data-copy operation. We ignore both
-  // notifications here.
-  auto on_success = [](brillo::StreamPtr, brillo::StreamPtr, uint64_t) {};
-  auto on_error = [](brillo::StreamPtr, brillo::StreamPtr,
-                     const brillo::Error*) {};
-  brillo::stream_utils::CopyData(
-      std::move(src_stream), std::move(dest_stream), base::Bind(on_success),
-      base::Bind(on_error));
-}
-
-}  // anonymous namespace
-
-const char ProtocolHandler::kHttp[] = "http";
+const char ProtocolHandler::kHttp[] =  "http";
 const char ProtocolHandler::kHttps[] = "https";
 
-ProtocolHandler::ProtocolHandler(const std::string& name, DBusServer* server)
-    : name_{name}, server_{server} {
-}
-
-ProtocolHandler::~ProtocolHandler() {
-  // Remove any existing handlers, so the web server knows that we don't
-  // need them anymore.
-
-  // We need to get a copy of the map keys since removing the handlers will
-  // modify the map in the middle of the loop and that's not a good thing.
-  auto handler_ids = brillo::GetMapKeys(request_handlers_);
-  for (int handler_id : handler_ids) {
-    RemoveHandler(handler_id);
-  }
-}
-
-std::string ProtocolHandler::GetName() const {
-  return name_;
-}
-
-std::set<uint16_t> ProtocolHandler::GetPorts() const {
-  std::set<uint16_t> ports;
-  for (const auto& pair : proxies_)
-    ports.insert(pair.second->port());
-  return ports;
-}
-
-std::set<std::string> ProtocolHandler::GetProtocols() const {
-  std::set<std::string> protocols;
-  for (const auto& pair : proxies_)
-    protocols.insert(pair.second->protocol());
-  return protocols;
-}
-
-brillo::Blob ProtocolHandler::GetCertificateFingerprint() const {
-  brillo::Blob fingerprint;
-  for (const auto& pair : proxies_) {
-    fingerprint = pair.second->certificate_fingerprint();
-    if (!fingerprint.empty())
-      break;
-  }
-  return fingerprint;
-}
-
-int ProtocolHandler::AddHandler(
-    const std::string& url,
-    const std::string& method,
-    std::unique_ptr<RequestHandlerInterface> handler) {
-  request_handlers_.emplace(
-      ++last_handler_id_,
-      HandlerMapEntry{url, method,
-                      std::map<ProtocolHandlerProxyInterface*, std::string>{},
-                      std::move(handler)});
-  // For each instance of remote protocol handler object sharing the same name,
-  // add the request handler.
-  for (const auto& pair : proxies_) {
-    pair.second->AddRequestHandlerAsync(
-        url,
-        method,
-        server_->service_name_,
-        base::Bind(&ProtocolHandler::AddHandlerSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   last_handler_id_,
-                   pair.second),
-        base::Bind(&ProtocolHandler::AddHandlerError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   last_handler_id_));
-  }
-  return last_handler_id_;
-}
-
-int ProtocolHandler::AddHandlerCallback(
-    const std::string& url,
-    const std::string& method,
-    const base::Callback<RequestHandlerInterface::HandlerSignature>&
-        handler_callback) {
-  std::unique_ptr<RequestHandlerInterface> handler{
-      new RequestHandlerCallback{handler_callback}};
-  return AddHandler(url, method, std::move(handler));
-}
-
-bool ProtocolHandler::RemoveHandler(int handler_id) {
-  auto p = request_handlers_.find(handler_id);
-  if (p == request_handlers_.end())
-    return false;
-
-  for (const auto& pair : p->second.remote_handler_ids) {
-    pair.first->RemoveRequestHandlerAsync(
-        pair.second,
-        base::Bind(&base::DoNothing),
-        base::Bind(&IgnoreDBusError));
-  }
-
-  request_handlers_.erase(p);
-  return true;
-}
-
-void ProtocolHandler::Connect(ProtocolHandlerProxyInterface* proxy) {
-  proxies_.emplace(proxy->GetObjectPath(), proxy);
-  for (const auto& pair : request_handlers_) {
-    proxy->AddRequestHandlerAsync(
-        pair.second.url,
-        pair.second.method,
-        server_->service_name_,
-        base::Bind(&ProtocolHandler::AddHandlerSuccess,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   pair.first,
-                   proxy),
-        base::Bind(&ProtocolHandler::AddHandlerError,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   pair.first));
-  }
-}
-
-void ProtocolHandler::Disconnect(const dbus::ObjectPath& object_path) {
-  proxies_.erase(object_path);
-  if (proxies_.empty())
-    remote_handler_id_map_.clear();
-  for (auto& pair : request_handlers_)
-    pair.second.remote_handler_ids.clear();
-}
-
-void ProtocolHandler::AddHandlerSuccess(int handler_id,
-                                        ProtocolHandlerProxyInterface* proxy,
-                                        const std::string& remote_handler_id) {
-  auto p = request_handlers_.find(handler_id);
-  CHECK(p != request_handlers_.end());
-  p->second.remote_handler_ids.emplace(proxy, remote_handler_id);
-
-  remote_handler_id_map_.emplace(remote_handler_id, handler_id);
-}
-
-void ProtocolHandler::AddHandlerError(int handler_id, brillo::Error* error) {
-  // Nothing to do at the moment.
-}
-
-bool ProtocolHandler::ProcessRequest(const std::string& protocol_handler_id,
-                                     const std::string& remote_handler_id,
-                                     const std::string& request_id,
-                                     std::unique_ptr<Request> request,
-                                     brillo::ErrorPtr* error) {
-  request_id_map_.emplace(request_id, protocol_handler_id);
-  auto id_iter = remote_handler_id_map_.find(remote_handler_id);
-  if (id_iter == remote_handler_id_map_.end()) {
-    brillo::Error::AddToPrintf(error, FROM_HERE,
-                               brillo::errors::dbus::kDomain,
-                               DBUS_ERROR_FAILED,
-                               "Unknown request handler '%s'",
-                               remote_handler_id.c_str());
-    return false;
-  }
-  auto handler_iter = request_handlers_.find(id_iter->second);
-  if (handler_iter == request_handlers_.end()) {
-    brillo::Error::AddToPrintf(error, FROM_HERE,
-                               brillo::errors::dbus::kDomain,
-                               DBUS_ERROR_FAILED,
-                               "Handler # %d is no longer available",
-                               id_iter->second);
-    return false;
-  }
-  handler_iter->second.handler->HandleRequest(
-      std::move(request),
-      std::unique_ptr<Response>{new ResponseImpl{this, request_id}});
-  return true;
-}
-
-void ProtocolHandler::CompleteRequest(
-    const std::string& request_id,
-    int status_code,
-    const std::multimap<std::string, std::string>& headers,
-    brillo::StreamPtr data_stream) {
-  ProtocolHandlerProxyInterface* proxy =
-      GetRequestProtocolHandlerProxy(request_id);
-  if (!proxy)
-    return;
-
-  std::vector<std::tuple<std::string, std::string>> header_list;
-  header_list.reserve(headers.size());
-  for (const auto& pair : headers)
-    header_list.emplace_back(pair.first, pair.second);
-
-  int64_t data_size = -1;
-  if (data_stream->CanGetSize())
-    data_size = data_stream->GetRemainingSize();
-  proxy->CompleteRequestAsync(
-      request_id, status_code, header_list, data_size,
-      base::Bind(&WriteResponseData, base::Passed(&data_stream)),
-      base::Bind(&IgnoreDBusError));
-}
-
-void ProtocolHandler::GetFileData(
-    const std::string& request_id,
-    int file_id,
-    const base::Callback<void(brillo::StreamPtr)>& success_callback,
-    const base::Callback<void(brillo::Error*)>& error_callback) {
-  ProtocolHandlerProxyInterface* proxy =
-      GetRequestProtocolHandlerProxy(request_id);
-  CHECK(proxy);
-
-  // Store the success/error callback in a shared object so it can be referenced
-  // by the two wrapper callbacks. Since the original callbacks MAY contain
-  // move-only types, copying the base::Callback object is generally unsafe and
-  // may destroy the source object of the copy (despite the fact that it is
-  // constant). So, here we move both callbacks to |Callbacks| structure and
-  // use a shared pointer to it in both success and error callback wrappers.
-  struct Callbacks {
-    base::Callback<void(brillo::StreamPtr)> on_success;
-    base::Callback<void(brillo::Error*)> on_error;
-  };
-  auto callbacks = std::make_shared<Callbacks>();
-  callbacks->on_success = success_callback;
-  callbacks->on_error = error_callback;
-
-  auto on_success = [callbacks](const dbus::FileDescriptor& fd) {
-    brillo::ErrorPtr error;
-    // Unfortunately there is no way to take ownership of the file descriptor
-    // since |fd| is a const reference, so duplicate the descriptor.
-    int dupfd = dup(fd.value());
-    auto stream = brillo::FileStream::FromFileDescriptor(dupfd, true, &error);
-    if (!stream)
-      return callbacks->on_error.Run(error.get());
-    callbacks->on_success.Run(std::move(stream));
-  };
-  auto on_error = [callbacks](brillo::Error* error) {
-    callbacks->on_error.Run(error);
-  };
-
-  proxy->GetRequestFileDataAsync(request_id, file_id, base::Bind(on_success),
-                                 base::Bind(on_error));
-}
-
-ProtocolHandler::ProtocolHandlerProxyInterface*
-ProtocolHandler::GetRequestProtocolHandlerProxy(
-    const std::string& request_id) const {
-  auto iter = request_id_map_.find(request_id);
-  if (iter == request_id_map_.end()) {
-    LOG(ERROR) << "Can't find pending request with ID " << request_id;
-    return nullptr;
-  }
-  std::string handler_id = iter->second;
-  auto find_proxy_by_id = [handler_id](decltype(*proxies_.begin()) pair) {
-    return pair.second->id() == handler_id;
-  };
-  auto proxy_iter = std::find_if(proxies_.begin(), proxies_.end(),
-                                 find_proxy_by_id);
-  if (proxy_iter == proxies_.end()) {
-    LOG(WARNING) << "Completing a request after the handler proxy is removed";
-    return nullptr;
-  }
-  return proxy_iter->second;
-}
-
-
 }  // namespace libwebserv
diff --git a/libwebserv/protocol_handler.h b/libwebserv/protocol_handler.h
index 2c2dee5..c4a9bef 100644
--- a/libwebserv/protocol_handler.h
+++ b/libwebserv/protocol_handler.h
@@ -15,71 +15,52 @@
 #ifndef WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_
 #define WEBSERVER_LIBWEBSERV_PROTOCOL_HANDLER_H_
 
-#include <map>
 #include <memory>
 #include <set>
 #include <string>
-#include <vector>
 
 #include <base/callback_forward.h>
 #include <base/macros.h>
-#include <base/memory/weak_ptr.h>
-#include <brillo/errors/error.h>
 #include <brillo/secure_blob.h>
-#include <brillo/streams/stream.h>
-#include <dbus/object_path.h>
 
 #include <libwebserv/export.h>
 #include <libwebserv/request_handler_interface.h>
 
-namespace org {
-namespace chromium {
-namespace WebServer {
-
-class ProtocolHandlerProxyInterface;
-
-}  // namespace WebServer
-}  // namespace chromium
-}  // namespace org
-
 namespace libwebserv {
 
-class DBusServer;
-class Request;
-
 // Wrapper around a protocol handler (e.g. HTTP or HTTPs).
 // ProtocolHandler allows consumers to add request handlers on a given protocol.
 // When the ProtocolHandler is connected, allows users to read port and protocol
 // information.
-class LIBWEBSERV_EXPORT ProtocolHandler final {
+class LIBWEBSERV_EXPORT ProtocolHandler {
  public:
-  ProtocolHandler(const std::string& name, DBusServer* server);
-  ~ProtocolHandler();
+  ProtocolHandler() = default;
+  virtual ~ProtocolHandler() = default;
 
-  // Returns true if the protocol handler object is connected to the web server
-  // daemon's proxy object and is capable of processing incoming requests.
-  bool IsConnected() const { return !proxies_.empty(); }
+  // Returns true if the protocol handler object is backed by a ProtocolHandler
+  // on the remote web server and is capable of processing incoming requests.
+  virtual bool IsConnected() const = 0;
 
   // Handler's name identifier (as provided in "name" setting of config file).
   // Standard/default handler names are "http" and "https".
-  std::string GetName() const;
+  virtual std::string GetName() const = 0;
 
   // Returns the ports the handler is bound to. There could be multiple.
   // If the handler is not connected to the server, this will return an empty
   // set.
-  std::set<uint16_t> GetPorts() const;
+  virtual std::set<uint16_t> GetPorts() const = 0;
 
   // Returns the transport protocol that is served by this handler.
   // Can be either "http" or "https".
   // If the handler is not connected to the server, this will return an empty
   // set.
-  std::set<std::string> GetProtocols() const;
+  virtual std::set<std::string> GetProtocols() const = 0;
 
   // Returns a SHA-256 fingerprint of HTTPS certificate used. Returns an empty
   // byte buffer if this handler does not serve the HTTPS protocol.
   // If the handler is not connected to the server, this will return an empty
   // array.
-  brillo::Blob GetCertificateFingerprint() const;
+  virtual brillo::Blob GetCertificateFingerprint() const = 0;
 
   // Adds a request handler for given |url|. If the |url| ends with a '/', this
   // makes the handler respond to any URL beneath this path.
@@ -106,106 +87,25 @@
   // available. This also happens when the web server goes away and then comes
   // back (e.g. restarted). So, there is no need to re-register the handlers
   // once the web server process is restarted.
-  int AddHandler(const std::string& url,
-                 const std::string& method,
-                 std::unique_ptr<RequestHandlerInterface> handler);
+  virtual int AddHandler(const std::string& url,
+                         const std::string& method,
+                         std::unique_ptr<RequestHandlerInterface> handler) = 0;
 
   // Similar to AddHandler() above but the handler is just a callback function.
-  int AddHandlerCallback(
+  virtual int AddHandlerCallback(
       const std::string& url,
       const std::string& method,
       const base::Callback<RequestHandlerInterface::HandlerSignature>&
-          handler_callback);
+          handler_callback) = 0;
 
   // Removes the handler with the specified |handler_id|.
   // Returns false if the handler with the given ID is not found.
-  bool RemoveHandler(int handler_id);
+  virtual bool RemoveHandler(int handler_id) = 0;
 
   static const char kHttp[];
   static const char kHttps[];
 
  private:
-  friend class FileInfo;
-  friend class DBusServer;
-  friend class ResponseImpl;
-
-  using ProtocolHandlerProxyInterface =
-      org::chromium::WebServer::ProtocolHandlerProxyInterface;
-
-  struct LIBWEBSERV_PRIVATE HandlerMapEntry {
-    std::string url;
-    std::string method;
-    std::map<ProtocolHandlerProxyInterface*, std::string> remote_handler_ids;
-    std::unique_ptr<RequestHandlerInterface> handler;
-  };
-
-  // Called by the DBusServer class when the D-Bus proxy object gets connected
-  // to the web server daemon.
-  LIBWEBSERV_PRIVATE void Connect(ProtocolHandlerProxyInterface* proxy);
-
-  // Called by the DBusServer class when the D-Bus proxy object gets
-  // disconnected from the web server daemon.
-  LIBWEBSERV_PRIVATE void Disconnect(const dbus::ObjectPath& object_path);
-
-  // Asynchronous callbacks to handle successful or failed request handler
-  // registration over D-Bus.
-  LIBWEBSERV_PRIVATE void AddHandlerSuccess(
-      int handler_id,
-      ProtocolHandlerProxyInterface* proxy,
-      const std::string& remote_handler_id);
-  LIBWEBSERV_PRIVATE void AddHandlerError(int handler_id,
-                                          brillo::Error* error);
-
-  // Called by DBusServer when an incoming request is dispatched.
-  LIBWEBSERV_PRIVATE bool ProcessRequest(const std::string& protocol_handler_id,
-                                         const std::string& remote_handler_id,
-                                         const std::string& request_id,
-                                         std::unique_ptr<Request> request,
-                                         brillo::ErrorPtr* error);
-
-  // Called by Response object to finish the request and send response data.
-  LIBWEBSERV_PRIVATE void CompleteRequest(
-      const std::string& request_id,
-      int status_code,
-      const std::multimap<std::string, std::string>& headers,
-      brillo::StreamPtr data_stream);
-
-  // Makes a call to the (remote) web server request handler over D-Bus to
-  // obtain the file content of uploaded file (identified by |file_id|) during
-  // request with |request_id|.
-  LIBWEBSERV_PRIVATE void GetFileData(
-      const std::string& request_id,
-      int file_id,
-      const base::Callback<void(brillo::StreamPtr)>& success_callback,
-      const base::Callback<void(brillo::Error*)>& error_callback);
-
-  // A helper method to obtain a corresponding protocol handler D-Bus proxy for
-  // outstanding request with ID |request_id|.
-  LIBWEBSERV_PRIVATE ProtocolHandlerProxyInterface*
-      GetRequestProtocolHandlerProxy(const std::string& request_id) const;
-
-  // Protocol Handler name.
-  std::string name_;
-  // Back reference to the server object.
-  DBusServer* server_{nullptr};
-  // Handler data map. The key is the client-facing request handler ID returned
-  // by AddHandler() when registering the handler.
-  std::map<int, HandlerMapEntry> request_handlers_;
-  // The counter to generate new handler IDs.
-  int last_handler_id_{0};
-  // Map of remote handler IDs (GUID strings) to client-facing request handler
-  // IDs (int) which are returned by AddHandler() and used as a key in
-  // |request_handlers_|.
-  std::map<std::string, int> remote_handler_id_map_;
-  // Remote D-Bus proxies for the server protocol handler objects.
-  // There could be multiple protocol handlers with the same name (to make
-  // it possible to server the same requests on different ports, for example).
-  std::map<dbus::ObjectPath, ProtocolHandlerProxyInterface*> proxies_;
-  // A map of request ID to protocol handler ID. Used to locate the appropriate
-  // protocol handler D-Bus proxy for given request.
-  std::map<std::string, std::string> request_id_map_;
-
-  base::WeakPtrFactory<ProtocolHandler> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(ProtocolHandler);
 };
 
diff --git a/libwebserv/request.cc b/libwebserv/request.cc
index 959b294..5d7abf7 100644
--- a/libwebserv/request.cc
+++ b/libwebserv/request.cc
@@ -18,11 +18,11 @@
 #include <brillo/http/http_utils.h>
 #include <brillo/streams/file_stream.h>
 
-#include <libwebserv/protocol_handler.h>
+#include <libwebserv/dbus_protocol_handler.h>
 
 namespace libwebserv {
 
-FileInfo::FileInfo(ProtocolHandler* handler,
+FileInfo::FileInfo(DBusProtocolHandler* handler,
                    int file_id,
                    const std::string& request_id,
                    const std::string& file_name,
@@ -45,7 +45,7 @@
                         error_callback);
 }
 
-RequestImpl::RequestImpl(ProtocolHandler* handler,
+RequestImpl::RequestImpl(DBusProtocolHandler* handler,
                          const std::string& url,
                          const std::string& method)
     : Request{url, method}, handler_{handler} {
diff --git a/libwebserv/request.h b/libwebserv/request.h
index ce8d82b..2950d1b 100644
--- a/libwebserv/request.h
+++ b/libwebserv/request.h
@@ -33,7 +33,7 @@
 
 namespace libwebserv {
 
-class ProtocolHandler;
+class DBusProtocolHandler;
 
 using PairOfStrings = std::pair<std::string, std::string>;
 
@@ -51,14 +51,14 @@
  private:
   friend class DBusServer;
 
-  LIBWEBSERV_PRIVATE FileInfo(ProtocolHandler* handler,
+  LIBWEBSERV_PRIVATE FileInfo(DBusProtocolHandler* handler,
                               int file_id,
                               const std::string& request_id,
                               const std::string& file_name,
                               const std::string& content_type,
                               const std::string& transfer_encoding);
 
-  ProtocolHandler* handler_{nullptr};
+  DBusProtocolHandler* handler_{nullptr};
   int file_id_{0};
   std::string request_id_;
   std::string file_name_;
diff --git a/libwebserv/request_impl.h b/libwebserv/request_impl.h
index 2c172ec..c2dc2a4 100644
--- a/libwebserv/request_impl.h
+++ b/libwebserv/request_impl.h
@@ -24,6 +24,8 @@
 
 namespace libwebserv {
 
+class DBusProtocolHandler;
+
 // Implementation of the Request interface.
 class RequestImpl final : public Request {
  public:
@@ -33,10 +35,10 @@
  private:
   friend class DBusServer;
 
-  LIBWEBSERV_PRIVATE RequestImpl(ProtocolHandler* handler,
+  LIBWEBSERV_PRIVATE RequestImpl(DBusProtocolHandler* handler,
                                  const std::string& url,
                                  const std::string& method);
-  ProtocolHandler* handler_{nullptr};
+  DBusProtocolHandler* handler_{nullptr};
   base::File raw_data_fd_;
   bool last_posted_data_was_file_{false};
 
diff --git a/libwebserv/response.cc b/libwebserv/response.cc
index bedc10c..c87a6c0 100644
--- a/libwebserv/response.cc
+++ b/libwebserv/response.cc
@@ -23,11 +23,11 @@
 #include <brillo/mime_utils.h>
 #include <brillo/streams/memory_stream.h>
 #include <brillo/strings/string_utils.h>
-#include <libwebserv/protocol_handler.h>
+#include <libwebserv/dbus_protocol_handler.h>
 
 namespace libwebserv {
 
-ResponseImpl::ResponseImpl(ProtocolHandler* handler,
+ResponseImpl::ResponseImpl(DBusProtocolHandler* handler,
                            const std::string& request_id)
     : handler_{handler}, request_id_{request_id} {
 }
diff --git a/libwebserv/response_impl.h b/libwebserv/response_impl.h
index 81b4faa..c66ea57 100644
--- a/libwebserv/response_impl.h
+++ b/libwebserv/response_impl.h
@@ -25,6 +25,8 @@
 
 namespace libwebserv {
 
+class DBusProtocolHandler;
+
 // Implementation of the Response interface.
 class ResponseImpl final : public Response {
  public:
@@ -49,14 +51,14 @@
   void ReplyWithErrorNotFound() override;
 
  private:
-  friend class ProtocolHandler;
+  friend class DBusProtocolHandler;
 
-  LIBWEBSERV_PRIVATE ResponseImpl(ProtocolHandler* handler,
+  LIBWEBSERV_PRIVATE ResponseImpl(DBusProtocolHandler* handler,
                                   const std::string& request_id);
 
   LIBWEBSERV_PRIVATE void SendResponse();
 
-  ProtocolHandler* handler_{nullptr};
+  DBusProtocolHandler* handler_{nullptr};
   std::string request_id_;
   int status_code_{0};
   brillo::StreamPtr data_stream_;