Expose GetDataStream() method for HTTP request object

Request::GetDataStream() can be used to read large HTTP request
data asynchronously using streaming I/O.

BUG: 24166746
Change-Id: I37d6b7d1477155e97eee62cd1d2261a9db8719b0
diff --git a/buffet/webserv_client.cc b/buffet/webserv_client.cc
index 37c9716..d8a8471 100644
--- a/buffet/webserv_client.cc
+++ b/buffet/webserv_client.cc
@@ -13,6 +13,7 @@
 #include <libwebserv/server.h>
 
 #include "buffet/dbus_constants.h"
+#include "buffet/socket_stream.h"
 
 namespace buffet {
 
@@ -29,12 +30,38 @@
   std::string GetFirstHeader(const std::string& name) const override {
     return request_->GetFirstHeader(name);
   }
+
+  // TODO(avakulenko): Remove this method and rewrite all call sites in libweave
+  // to use GetDataStream() instead.
   const std::vector<uint8_t>& GetData() const override {
-    return request_->GetData();
+    if (!request_data_)
+      return *request_data_;
+
+    request_data_.reset(new std::vector<uint8_t>);
+    auto stream = request_->GetDataStream();
+    if (stream) {
+      if (stream->CanGetSize())
+        request_data_->reserve(stream->GetRemainingSize());
+      std::vector<uint8_t> buffer(16 * 1024);  // 16K seems to be good enough.
+      size_t sz = 0;
+      while (stream->ReadBlocking(buffer.data(), buffer.size(), &sz, nullptr) &&
+             sz > 0) {
+        request_data_->insert(request_data_->end(),
+                              buffer.data(), buffer.data() + sz);
+      }
+    }
+    return *request_data_;
+  }
+
+  std::unique_ptr<weave::Stream> GetDataStream() const override {
+    auto stream = std::unique_ptr<weave::Stream>{
+        new SocketStream{request_->GetDataStream()}};
+    return stream;
   }
 
  private:
   std::unique_ptr<libwebserv::Request> request_;
+  mutable std::unique_ptr<std::vector<uint8_t>> request_data_;
 
   DISALLOW_COPY_AND_ASSIGN(RequestImpl);
 };