Add https parsing

This is yet another step in parsing HTTP requests.

Tested:
'''
curl -vvvv -k --user "root:0penBmc" -H "Content-Type: application/json" \
-X POST https://192.168.7.2/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate \
-d '{ \
"TransferProtocol":"TFTP", \
"ImageURI":"https://192.168.7.1/myfile.bin" \
}'
'''

Returns ActionParameterNotSupported

TransferProtocol: Omitted
ImageURI: https://192.168.7.1/myfile.bin
Returns ActionParameterNotSupported

TransferProtocol: Omitted
ImageURI: 192.168.7.1/myfile.bin
Returns ActionParameterValueTypeError

TransferProtocol: Bad
ImageURI: https:/192.168.7.1/myfile.bin
Returns: ActionParameterNotSupported

No changes to GET requests, so Redfish Service Validator not necessary.

Change-Id: Ibf4b69877031f3b8617412c06d40f2d0d0827ac3
Signed-off-by: Ed Tanous <ed@tanous.net>
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 6895cb4..2a40f8a 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -464,11 +464,15 @@
                 res, imageURI, "ImageURI", "UpdateService.SimpleUpdate");
             return std::nullopt;
         }
-        // OpenBMC currently only supports TFTP
+        // OpenBMC currently only supports TFTP or HTTPS
         if (*transferProtocol == "TFTP")
         {
             imageURI = "tftp://" + imageURI;
         }
+        else if (*transferProtocol == "HTTPS")
+        {
+            imageURI = "https://" + imageURI;
+        }
         else
         {
             messages::actionParameterNotSupported(res, "TransferProtocol",
@@ -499,6 +503,14 @@
             return std::nullopt;
         }
     }
+    else if (url->scheme() == "https")
+    {
+        // Empty paths default to "/"
+        if (url->encoded_path().empty())
+        {
+            url->set_encoded_path("/");
+        }
+    }
     else
     {
         messages::actionParameterNotSupported(res, "ImageURI", imageURI);
@@ -515,6 +527,13 @@
     return *url;
 }
 
+inline void doHttpsUpdate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                          const boost::urls::url_view_base& url)
+{
+    messages::actionParameterNotSupported(asyncResp->res, "ImageURI",
+                                          url.buffer());
+}
+
 inline void doTftpUpdate(const crow::Request& req,
                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const boost::urls::url_view_base& url)
@@ -606,6 +625,10 @@
     {
         doTftpUpdate(req, asyncResp, *url);
     }
+    else if (url->scheme() == "https")
+    {
+        doHttpsUpdate(asyncResp, *url);
+    }
     else
     {
         messages::actionParameterNotSupported(asyncResp->res, "ImageURI",
@@ -841,6 +864,7 @@
         "/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate";
 
     nlohmann::json::array_t allowed;
+    allowed.emplace_back(update_service::TransferProtocolType::HTTPS);
 
     if constexpr (BMCWEB_INSECURE_PUSH_STYLE_NOTIFICATION)
     {
diff --git a/test/redfish-core/lib/update_service_test.cpp b/test/redfish-core/lib/update_service_test.cpp
index 87af3f1..11b4479 100644
--- a/test/redfish-core/lib/update_service_test.cpp
+++ b/test/redfish-core/lib/update_service_test.cpp
@@ -43,7 +43,7 @@
         EXPECT_EQ(ret->scheme(), "tftp");
     }
     {
-        // Both protocl and schema on url
+        // Both protocol and schema on url
         std::optional<boost::urls::url> ret =
             parseSimpleUpdateUrl("tftp://1.1.1.1/path", "TFTP", res);
         ASSERT_TRUE(ret);
@@ -57,6 +57,63 @@
     }
 }
 
+TEST(UpdateService, ParseHTTPSPostitive)
+{
+    crow::Response res;
+    {
+        // No protocol, schema on url
+        std::optional<boost::urls::url> ret =
+            parseSimpleUpdateUrl("https://1.1.1.1/path", std::nullopt, res);
+        ASSERT_TRUE(ret);
+        if (!ret)
+        {
+            return;
+        }
+        EXPECT_EQ(ret->encoded_host_and_port(), "1.1.1.1");
+        EXPECT_EQ(ret->encoded_path(), "/path");
+        EXPECT_EQ(ret->scheme(), "https");
+    }
+    {
+        // Protocol, no schema on url
+        std::optional<boost::urls::url> ret =
+            parseSimpleUpdateUrl("1.1.1.1/path", "HTTPS", res);
+        ASSERT_TRUE(ret);
+        if (!ret)
+        {
+            return;
+        }
+        EXPECT_EQ(ret->encoded_host_and_port(), "1.1.1.1");
+        EXPECT_EQ(ret->encoded_path(), "/path");
+        EXPECT_EQ(ret->scheme(), "https");
+    }
+    {
+        // Both protocol and schema on url with path
+        std::optional<boost::urls::url> ret =
+            parseSimpleUpdateUrl("https://1.1.1.1/path", "HTTPS", res);
+        ASSERT_TRUE(ret);
+        if (!ret)
+        {
+            return;
+        }
+        EXPECT_EQ(ret->encoded_host_and_port(), "1.1.1.1");
+        EXPECT_EQ(ret->encoded_path(), "/path");
+        EXPECT_EQ(ret->scheme(), "https");
+    }
+    {
+        // Both protocol and schema on url without path
+        std::optional<boost::urls::url> ret =
+            parseSimpleUpdateUrl("https://1.1.1.1", "HTTPS", res);
+        ASSERT_TRUE(ret);
+        if (!ret)
+        {
+            return;
+        }
+        EXPECT_EQ(ret->encoded_host_and_port(), "1.1.1.1");
+        EXPECT_EQ(ret->encoded_path(), "/");
+        EXPECT_EQ(ret->scheme(), "https");
+    }
+}
+
 TEST(UpdateService, ParseTFTPNegative)
 {
     crow::Response res;