Reponse: Fix incomplete implementation in write

Write function in http_response.hpp missing implementation for first
write after changing from filebody.
Usecase:
Current resonse type is filebody. Developer tries to change the body
type to stringbody by calling write function.
Observed:
The write fails to update the body type.
Expected:
Write should succeed and body should change to string body.

Tested:
Unit test has been added for crow::Response.
Manual sanity test done for file offloads using curl.

Change-Id: Icbf8585b5b04c3ac5120d7b334c13d89ed3eb4aa
Signed-off-by: Abhilash Raju <abhilash.kollam@gmail.com>
diff --git a/http/http_response.hpp b/http/http_response.hpp
index a5f95a9..ec54a90 100644
--- a/http/http_response.hpp
+++ b/http/http_response.hpp
@@ -12,7 +12,7 @@
 #include <optional>
 #include <string>
 #include <string_view>
-
+#include <utility>
 namespace crow
 {
 
@@ -262,7 +262,10 @@
             str->body() += bodyPart;
             return;
         }
-        response.emplace<string_response>(result(), 11, std::move(bodyPart));
+        http::header<false> headTemp = std::move(fields());
+        string_response& stringResponse =
+            response.emplace<string_response>(std::move(headTemp));
+        stringResponse.body() = std::move(bodyPart);
     }
 
     void end()
diff --git a/meson.build b/meson.build
index f3e0ed3..002b949 100644
--- a/meson.build
+++ b/meson.build
@@ -409,6 +409,7 @@
   'test/http/crow_getroutes_test.cpp',
   'test/http/http_connection_test.cpp',
   'test/http/router_test.cpp',
+  'test/http/http_response_test.cpp',
   'test/http/utility_test.cpp',
   'test/http/verb_test.cpp',
   'test/include/dbus_utility_test.cpp',
diff --git a/test/http/http_response_test.cpp b/test/http/http_response_test.cpp
new file mode 100644
index 0000000..c644ea9
--- /dev/null
+++ b/test/http/http_response_test.cpp
@@ -0,0 +1,91 @@
+#include "boost/beast/core/flat_buffer.hpp"
+#include "boost/beast/http/serializer.hpp"
+#include "http/http_response.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <thread>
+
+#include "gtest/gtest.h"
+namespace
+{
+void addHeaders(crow::Response& res)
+{
+    res.addHeader("myheader", "myvalue");
+    res.keepAlive(true);
+    res.result(boost::beast::http::status::ok);
+}
+void verifyHeaders(crow::Response& res)
+{
+    EXPECT_EQ(res.getHeaderValue("myheader"), "myvalue");
+    EXPECT_EQ(res.keepAlive(), true);
+    EXPECT_EQ(res.result(), boost::beast::http::status::ok);
+}
+
+std::string makeFile()
+{
+    std::filesystem::path path = std::filesystem::temp_directory_path();
+    path /= "bmcweb_http_response_test_XXXXXXXXXXX";
+    std::string stringPath = path.string();
+    int fd = mkstemp(stringPath.data());
+    EXPECT_GT(fd, 0);
+    std::string_view sample = "sample text";
+    EXPECT_EQ(write(fd, sample.data(), sample.size()), sample.size());
+    return stringPath;
+}
+TEST(HttpResponse, Defaults)
+{
+    crow::Response res;
+    EXPECT_EQ(
+        boost::variant2::holds_alternative<crow::Response::string_response>(
+            res.response),
+        true);
+}
+TEST(HttpResponse, Headers)
+{
+    crow::Response res;
+    addHeaders(res);
+    verifyHeaders(res);
+}
+TEST(HttpResponse, StringBody)
+{
+    crow::Response res;
+    addHeaders(res);
+    std::string_view bodyvalue = "this is my new body";
+    res.write({bodyvalue.data(), bodyvalue.length()});
+    EXPECT_EQ(*res.body(), bodyvalue);
+    verifyHeaders(res);
+}
+TEST(HttpResponse, FileBody)
+{
+    crow::Response res;
+    addHeaders(res);
+    std::string path = makeFile();
+    res.openFile(path);
+
+    verifyHeaders(res);
+    std::filesystem::remove(path);
+}
+TEST(HttpResponse, BodyTransitions)
+{
+    crow::Response res;
+    addHeaders(res);
+    std::string path = makeFile();
+    res.openFile(path);
+
+    EXPECT_EQ(boost::variant2::holds_alternative<crow::Response::file_response>(
+                  res.response),
+              true);
+
+    verifyHeaders(res);
+    res.write("body text");
+
+    EXPECT_EQ(
+        boost::variant2::holds_alternative<crow::Response::string_response>(
+            res.response),
+        true);
+
+    verifyHeaders(res);
+    std::filesystem::remove(path);
+}
+} // namespace