Add url type safety to message registry

There are a number of places where we use message registry messages
incorrectly.  This patchset attempts to fix them, and invoke some type
safety when they're used such that they're more obvious to use.

Namely, it changes a number of the message registry methods to accept a
boost::urls::url_view for its argument instead of a const std::string&.
This forces the calling code to correctly encode a URL to use the
method, which should make it obvious that it's not for an ID, a property
name, or anything else.  In the course of doing this, several places
were found to be using the first argument incorrectly.

Tested:
curl --insecure --user root:0penBmc https://192.168.7.2/redfish/v1/Chassis/foobar

Returns:
{
  "error": {
    "@Message.ExtendedInfo": [
      {
        "@odata.type": "#Message.v1_1_1.Message",
        "Message": "The requested resource of type #Chassis.v1_16_0.Chassis named foobar was not found.",
        "MessageArgs": [
          "#Chassis.v1_16_0.Chassis",
          "foobar"
        ],
        "MessageId": "Base.1.8.1.ResourceNotFound",
        "MessageSeverity": "Critical",
        "Resolution": "Provide a valid resource identifier and resubmit the request."
      }
    ],
    "code": "Base.1.8.1.ResourceNotFound",
    "message": "The requested resource of type #Chassis.v1_16_0.Chassis named foobar was not found."
}

Identically to previously.

Also tested with IDs that contained % encoded characters, like
foobar%10, which gave the same result.

Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Icbb3bce5d190a260610087c9ef35e7becc5a50c7
diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
index 6064f77..9658f0b 100644
--- a/redfish-core/include/error_messages.hpp
+++ b/redfish-core/include/error_messages.hpp
@@ -16,6 +16,7 @@
 #pragma once
 #include "http_response.hpp"
 
+#include <boost/url/urls.hpp>
 #include <nlohmann/json.hpp>
 #include <source_location.hpp>
 
@@ -59,9 +60,10 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message ResourceMissingAtURI formatted to JSON */
-nlohmann::json resourceMissingAtURI(const std::string& arg1);
+nlohmann::json resourceMissingAtURI(const boost::urls::url_view& arg1);
 
-void resourceMissingAtURI(crow::Response& res, const std::string& arg1);
+void resourceMissingAtURI(crow::Response& res,
+                          const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats ActionParameterValueFormatError message into JSON
@@ -114,10 +116,11 @@
  * @param[in] arg2 Parameter of message that will replace %2 in its body.
  *
  * @returns Message ResourceAtUriUnauthorized formatted to JSON */
-nlohmann::json resourceAtUriUnauthorized(const std::string& arg1,
+nlohmann::json resourceAtUriUnauthorized(const boost::urls::url_view& arg1,
                                          const std::string& arg2);
 
-void resourceAtUriUnauthorized(crow::Response& res, const std::string& arg1,
+void resourceAtUriUnauthorized(crow::Response& res,
+                               const boost::urls::url_view& arg1,
                                const std::string& arg2);
 
 /**
@@ -249,9 +252,10 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message ResourceAtUriInUnknownFormat formatted to JSON */
-nlohmann::json resourceAtUriInUnknownFormat(const std::string& arg1);
+nlohmann::json resourceAtUriInUnknownFormat(const boost::urls::url_view& arg1);
 
-void resourceAtUriInUnknownFormat(crow::Response& res, const std::string& arg1);
+void resourceAtUriInUnknownFormat(crow::Response& res,
+                                  const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats ServiceDisabled message into JSON
@@ -358,9 +362,10 @@
  * @param[in] arg2 Parameter of message that will replace %2 in its body.
  *
  * @returns Message ResetRequired formatted to JSON */
-nlohmann::json resetRequired(const std::string& arg1, const std::string& arg2);
+nlohmann::json resetRequired(const boost::urls::url_view& arg1,
+                             const std::string& arg2);
 
-void resetRequired(crow::Response& res, const std::string& arg1,
+void resetRequired(crow::Response& res, const boost::urls::url_view& arg1,
                    const std::string& arg2);
 
 /**
@@ -426,9 +431,10 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message ResourceCreationConflict formatted to JSON */
-nlohmann::json resourceCreationConflict(const std::string& arg1);
+nlohmann::json resourceCreationConflict(const boost::urls::url_view& arg1);
 
-void resourceCreationConflict(crow::Response& res, const std::string& arg1);
+void resourceCreationConflict(crow::Response& res,
+                              const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats MaximumErrorsExceeded message into JSON
@@ -522,9 +528,10 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message CouldNotEstablishConnection formatted to JSON */
-nlohmann::json couldNotEstablishConnection(const std::string& arg1);
+nlohmann::json couldNotEstablishConnection(const boost::urls::url_view& arg1);
 
-void couldNotEstablishConnection(crow::Response& res, const std::string& arg1);
+void couldNotEstablishConnection(crow::Response& res,
+                                 const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats PropertyNotWritable message into JSON
@@ -603,10 +610,11 @@
  * @param[in] arg2 Parameter of message that will replace %2 in its body.
  *
  * @returns Message SourceDoesNotSupportProtocol formatted to JSON */
-nlohmann::json sourceDoesNotSupportProtocol(const std::string& arg1,
+nlohmann::json sourceDoesNotSupportProtocol(const boost::urls::url_view& arg1,
                                             const std::string& arg2);
 
-void sourceDoesNotSupportProtocol(crow::Response& res, const std::string& arg1,
+void sourceDoesNotSupportProtocol(crow::Response& res,
+                                  const boost::urls::url_view& arg1,
                                   const std::string& arg2);
 
 /**
@@ -627,9 +635,9 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message AccessDenied formatted to JSON */
-nlohmann::json accessDenied(const std::string& arg1);
+nlohmann::json accessDenied(const boost::urls::url_view& arg1);
 
-void accessDenied(crow::Response& res, const std::string& arg1);
+void accessDenied(crow::Response& res, const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats QueryNotSupported message into JSON
@@ -724,9 +732,9 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message InvalidObject formatted to JSON */
-nlohmann::json invalidObject(const std::string& arg1);
+nlohmann::json invalidObject(const boost::urls::url_view& arg1);
 
-void invalidObject(crow::Response& res, const std::string& arg1);
+void invalidObject(crow::Response& res, const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats ResourceInStandby message into JSON
@@ -946,7 +954,11 @@
  * @param[in] arg1 Parameter of message that will replace %1 in its body.
  *
  * @returns Message PasswordChangeRequired formatted to JSON */
-void passwordChangeRequired(crow::Response& res, const std::string& arg1);
+
+nlohmann::json passwordChangeRequired(const boost::urls::url_view& arg1);
+
+void passwordChangeRequired(crow::Response& res,
+                            const boost::urls::url_view& arg1);
 
 /**
  * @brief Formats InvalidUpload message into JSON
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 94de5a9..154de95 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -328,7 +328,8 @@
             indexStr.data(), indexStr.data() + indexStr.size(), index);
         if (ec != std::errc())
         {
-            messages::resourceMissingAtURI(asyncResp->res, entryID);
+            messages::resourceMissingAtURI(
+                asyncResp->res, crow::utility::urlFromPieces(entryID));
             return false;
         }
     }
@@ -337,7 +338,8 @@
         std::from_chars(tsStr.data(), tsStr.data() + tsStr.size(), timestamp);
     if (ec != std::errc())
     {
-        messages::resourceMissingAtURI(asyncResp->res, entryID);
+        messages::resourceMissingAtURI(asyncResp->res,
+                                       crow::utility::urlFromPieces(entryID));
         return false;
     }
     return true;
@@ -812,8 +814,7 @@
             (*diagnosticDataType != "OEM"))
         {
             BMCWEB_LOG_ERROR << "Wrong parameter values passed";
-            messages::invalidObject(asyncResp->res,
-                                    "System Dump creation parameters");
+            messages::internalError(asyncResp->res);
             return;
         }
     }
@@ -831,8 +832,7 @@
         {
             BMCWEB_LOG_ERROR
                 << "Wrong parameter value passed for 'DiagnosticDataType'";
-            messages::invalidObject(asyncResp->res,
-                                    "BMC Dump creation parameters");
+            messages::internalError(asyncResp->res);
             return;
         }
     }
@@ -1332,7 +1332,8 @@
                     }
                 }
                 // Requested ID was not found
-                messages::resourceMissingAtURI(asyncResp->res, targetID);
+                messages::resourceMissingAtURI(
+                    asyncResp->res, crow::utility::urlFromPieces(targetID));
             });
 }
 
@@ -1976,7 +1977,7 @@
         app, "/redfish/v1/Systems/system/LogServices/HostLogger/Entries/<str>/")
         .privileges(redfish::privileges::getLogEntry)
         .methods(boost::beast::http::verb::get)(
-            [](const crow::Request&,
+            [](const crow::Request& req,
                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                const std::string& param) {
                 const std::string& targetID = param;
@@ -1989,12 +1990,12 @@
                 auto [ptr, ec] = std::from_chars(targetID.data(), end, idInt);
                 if (ec == std::errc::invalid_argument)
                 {
-                    messages::resourceMissingAtURI(asyncResp->res, targetID);
+                    messages::resourceMissingAtURI(asyncResp->res, req.urlView);
                     return;
                 }
                 if (ec == std::errc::result_out_of_range)
                 {
-                    messages::resourceMissingAtURI(asyncResp->res, targetID);
+                    messages::resourceMissingAtURI(asyncResp->res, req.urlView);
                     return;
                 }
 
@@ -2026,7 +2027,7 @@
                 }
 
                 // Requested ID was not found
-                messages::resourceMissingAtURI(asyncResp->res, targetID);
+                messages::resourceMissingAtURI(asyncResp->res, req.urlView);
             });
 }
 
@@ -2253,7 +2254,7 @@
                  "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/")
         .privileges(redfish::privileges::getLogEntry)
         .methods(boost::beast::http::verb::get)(
-            [](const crow::Request&,
+            [](const crow::Request& req,
                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                const std::string& entryID) {
                 // Convert the unique ID back to a timestamp to find the entry
@@ -2304,7 +2305,7 @@
                 // Confirm that the entry ID matches what was requested
                 if (idStr != entryID)
                 {
-                    messages::resourceMissingAtURI(asyncResp->res, entryID);
+                    messages::resourceMissingAtURI(asyncResp->res, req.urlView);
                     return;
                 }
 
@@ -2642,7 +2643,8 @@
 
             if (filename.empty() || timestamp.empty())
             {
-                messages::resourceMissingAtURI(asyncResp->res, logID);
+                messages::resourceMissingAtURI(
+                    asyncResp->res, crow::utility::urlFromPieces(logID));
                 return;
             }
 
@@ -2774,11 +2776,12 @@
         "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/<str>/")
         .privileges(redfish::privileges::getLogEntry)
         .methods(boost::beast::http::verb::get)(
-            [](const crow::Request&,
+            [](const crow::Request& req,
                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                const std::string& logID, const std::string& fileName) {
                 auto getStoredLogCallback =
-                    [asyncResp, logID, fileName](
+                    [asyncResp, logID, fileName,
+                     url(boost::urls::url(req.urlView))](
                         const boost::system::error_code ec,
                         const std::vector<std::pair<
                             std::string, dbus::utility::DbusVariantType>>&
@@ -2801,23 +2804,20 @@
                         if (dbusFilename.empty() || dbusTimestamp.empty() ||
                             dbusFilepath.empty())
                         {
-                            messages::resourceMissingAtURI(asyncResp->res,
-                                                           fileName);
+                            messages::resourceMissingAtURI(asyncResp->res, url);
                             return;
                         }
 
                         // Verify the file name parameter is correct
                         if (fileName != dbusFilename)
                         {
-                            messages::resourceMissingAtURI(asyncResp->res,
-                                                           fileName);
+                            messages::resourceMissingAtURI(asyncResp->res, url);
                             return;
                         }
 
                         if (!std::filesystem::exists(dbusFilepath))
                         {
-                            messages::resourceMissingAtURI(asyncResp->res,
-                                                           fileName);
+                            messages::resourceMissingAtURI(asyncResp->res, url);
                             return;
                         }
                         std::ifstream ifs(dbusFilepath,
@@ -3456,7 +3456,7 @@
         app, "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/<str>/")
         .privileges(redfish::privileges::getLogEntry)
         .methods(boost::beast::http::verb::get)(
-            [](const crow::Request&,
+            [](const crow::Request& req,
                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                const std::string& targetID) {
                 uint16_t bootIndex = 0;
@@ -3464,7 +3464,7 @@
                 if (!parsePostCode(targetID, codeIndex, bootIndex))
                 {
                     // Requested ID was not found
-                    messages::resourceMissingAtURI(asyncResp->res, targetID);
+                    messages::resourceMissingAtURI(asyncResp->res, req.urlView);
                     return;
                 }
                 if (bootIndex == 0 || codeIndex == 0)
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index b3796a6..a5e8c23 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -802,7 +802,9 @@
         if (managedItem == nullptr)
         {
             BMCWEB_LOG_ERROR << "Failed to get chassis from config patch";
-            messages::invalidObject(response->res, it.key());
+            messages::invalidObject(response->res,
+                                    crow::utility::urlFromPieces(
+                                        "redfish", "v1", "Chassis", chassis));
             return CreatePIDRet::fail;
         }
     }
@@ -916,7 +918,9 @@
                 findChassis(managedObj, zonesStr[0], chassis) == nullptr)
             {
                 BMCWEB_LOG_ERROR << "Failed to get chassis from config patch";
-                messages::invalidObject(response->res, it.key());
+                messages::invalidObject(
+                    response->res, crow::utility::urlFromPieces(
+                                       "redfish", "v1", "Chassis", chassis));
                 return CreatePIDRet::fail;
             }
 
@@ -978,7 +982,8 @@
             {
                 BMCWEB_LOG_ERROR << "Invalid setpointoffset "
                                  << *setpointOffset;
-                messages::invalidObject(response->res, it.key());
+                messages::propertyValueNotInList(response->res, it.key(),
+                                                 "SetPointOffset");
                 return CreatePIDRet::fail;
             }
         }
@@ -1033,7 +1038,9 @@
             if (!dbus::utility::getNthStringFromPath(chassisId, 3, chassis))
             {
                 BMCWEB_LOG_ERROR << "Got invalid path " << chassisId;
-                messages::invalidObject(response->res, chassisId);
+                messages::invalidObject(
+                    response->res, crow::utility::urlFromPieces(
+                                       "redfish", "v1", "Chassis", chassisId));
                 return CreatePIDRet::fail;
             }
         }
@@ -1081,7 +1088,9 @@
                 findChassis(managedObj, zonesStrs[0], chassis) == nullptr)
             {
                 BMCWEB_LOG_ERROR << "Failed to get chassis from config patch";
-                messages::invalidObject(response->res, it.key());
+                messages::invalidObject(
+                    response->res, crow::utility::urlFromPieces(
+                                       "redfish", "v1", "Chassis", chassis));
                 return CreatePIDRet::fail;
             }
             output["Zones"] = std::move(zonesStrs);
@@ -1592,7 +1601,8 @@
                 if (createNewObject && it.value() == nullptr)
                 {
                     // can't delete a non-existent object
-                    messages::invalidObject(response->res, name);
+                    messages::propertyValueNotInList(response->res, it.value(),
+                                                     name);
                     continue;
                 }
 
@@ -1655,7 +1665,7 @@
                     if (chassis.empty())
                     {
                         BMCWEB_LOG_ERROR << "Failed to get chassis from config";
-                        messages::invalidObject(response->res, name);
+                        messages::internalError(response->res);
                         return;
                     }
 
@@ -1673,7 +1683,9 @@
                     {
                         BMCWEB_LOG_ERROR << "Failed to find chassis on dbus";
                         messages::resourceMissingAtURI(
-                            response->res, "/redfish/v1/Chassis/" + chassis);
+                            response->res,
+                            crow::utility::urlFromPieces("redfish", "v1",
+                                                         "Chassis", chassis));
                         return;
                     }
 
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index 1568c00..a66f460 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -19,6 +19,7 @@
 #include "persistent_data.hpp"
 
 #include <app.hpp>
+#include <http/utility.hpp>
 #include <registries/privilege_registry.hpp>
 
 namespace redfish
@@ -175,7 +176,7 @@
                 if ((pamrc != PAM_SUCCESS) && !isConfigureSelfOnly)
                 {
                     messages::resourceAtUriUnauthorized(
-                        asyncResp->res, std::string(req.url),
+                        asyncResp->res, req.urlView,
                         "Invalid username or password");
                     return;
                 }
@@ -212,8 +213,9 @@
                 if (session->isConfigureSelfOnly)
                 {
                     messages::passwordChangeRequired(
-                        asyncResp->res, "/redfish/v1/AccountService/Accounts/" +
-                                            session->username);
+                        asyncResp->res, crow::utility::urlFromPieces(
+                                            "redfish", "v1", "AccountService",
+                                            "Accounts", req.session->username));
                 }
 
                 fillSessionObject(asyncResp->res, *session);
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 1288815..6c61e40 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -931,8 +931,9 @@
                             << "Input swID " + *swId + " not found!";
                         messages::resourceMissingAtURI(
                             asyncResp->res,
-                            "/redfish/v1/UpdateService/FirmwareInventory/" +
-                                *swId);
+                            crow::utility::urlFromPieces(
+                                "redfish", "v1", "UpdateService",
+                                "FirmwareInventory", *swId));
                         return;
                     }
                     asyncResp->res.jsonValue["@odata.type"] =
diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
index 049cc56..b0e3b38 100644
--- a/redfish-core/lib/virtual_media.hpp
+++ b/redfish-core/lib/virtual_media.hpp
@@ -306,16 +306,9 @@
  *
  */
 inline std::optional<TransferProtocol>
-    getTransferProtocolFromUri(const std::string& imageUri)
+    getTransferProtocolFromUri(const boost::urls::url_view& imageUri)
 {
-    boost::urls::result<boost::urls::url_view> url =
-        boost::urls::parse_uri(boost::string_view(imageUri));
-    if (!url)
-    {
-        return {};
-    }
-
-    boost::string_view scheme = url->scheme();
+    boost::string_view scheme = imageUri.scheme();
     if (scheme == "smb")
     {
         return TransferProtocol::smb;
@@ -421,9 +414,15 @@
 
         return false;
     }
-
+    boost::urls::result<boost::urls::url_view> url =
+        boost::urls::parse_uri(boost::string_view(imageUrl));
+    if (!url)
+    {
+        messages::resourceAtUriInUnknownFormat(res, *url);
+        return {};
+    }
     std::optional<TransferProtocol> uriTransferProtocolType =
-        getTransferProtocolFromUri(imageUrl);
+        getTransferProtocolFromUri(*url);
 
     std::optional<TransferProtocol> paramTransferProtocolType =
         getTransferProtocolFromParam(transferProtocolType);
@@ -435,7 +434,7 @@
                             "contain specified protocol type from list: "
                             "(smb, https).";
 
-        messages::resourceAtUriInUnknownFormat(res, imageUrl);
+        messages::resourceAtUriInUnknownFormat(res, *url);
 
         return false;
     }
@@ -460,7 +459,7 @@
                             "contain specified protocol type or param "
                             "TransferProtocolType must be provided.";
 
-        messages::resourceAtUriInUnknownFormat(res, imageUrl);
+        messages::resourceAtUriInUnknownFormat(res, *url);
 
         return false;
     }
diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
index 5b5b696..2c98e23 100644
--- a/redfish-core/src/error_messages.cpp
+++ b/redfish-core/src/error_messages.cpp
@@ -16,6 +16,7 @@
 #include "http_response.hpp"
 
 #include <boost/beast/http/status.hpp>
+#include <boost/url/url.hpp>
 #include <error_messages.hpp>
 #include <logging.hpp>
 #include <nlohmann/json.hpp>
@@ -160,19 +161,21 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json resourceMissingAtURI(const std::string& arg1)
+nlohmann::json resourceMissingAtURI(const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.ResourceMissingAtURI"},
-        {"Message", "The resource at the URI " + arg1 + " was not found."},
-        {"MessageArgs", {arg1}},
+        {"Message", "The resource at the URI " + url + " was not found."},
+        {"MessageArgs", {url}},
         {"MessageSeverity", "Critical"},
         {"Resolution", "Place a valid resource at the URI or correct the "
                        "URI and resubmit the request."}};
 }
 
-void resourceMissingAtURI(crow::Response& res, const std::string& arg1)
+void resourceMissingAtURI(crow::Response& res,
+                          const boost::urls::url_view& arg1)
 {
     res.result(boost::beast::http::status::bad_request);
     addMessageToErrorJson(res.jsonValue, resourceMissingAtURI(arg1));
@@ -275,22 +278,24 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json resourceAtUriUnauthorized(const std::string& arg1,
+nlohmann::json resourceAtUriUnauthorized(const boost::urls::url_view& arg1,
                                          const std::string& arg2)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.ResourceAtUriUnauthorized"},
-        {"Message", "While accessing the resource at " + arg1 +
+        {"Message", "While accessing the resource at " + url +
                         ", the service received an authorization error " +
                         arg2 + "."},
-        {"MessageArgs", {arg1, arg2}},
+        {"MessageArgs", {url, arg2}},
         {"MessageSeverity", "Critical"},
         {"Resolution", "Ensure that the appropriate access is provided for "
                        "the service in order for it to access the URI."}};
 }
 
-void resourceAtUriUnauthorized(crow::Response& res, const std::string& arg1,
+void resourceAtUriUnauthorized(crow::Response& res,
+                               const boost::urls::url_view& arg1,
                                const std::string& arg2)
 {
     res.result(boost::beast::http::status::unauthorized);
@@ -559,20 +564,22 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json resourceAtUriInUnknownFormat(const std::string& arg1)
+nlohmann::json resourceAtUriInUnknownFormat(const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.ResourceAtUriInUnknownFormat"},
-        {"Message", "The resource at " + arg1 +
+        {"Message", "The resource at " + url +
                         " is in a format not recognized by the service."},
-        {"MessageArgs", {arg1}},
+        {"MessageArgs", {url}},
         {"MessageSeverity", "Critical"},
         {"Resolution", "Place an image or resource or file that is "
                        "recognized by the service at the URI."}};
 }
 
-void resourceAtUriInUnknownFormat(crow::Response& res, const std::string& arg1)
+void resourceAtUriInUnknownFormat(crow::Response& res,
+                                  const boost::urls::url_view& arg1)
 {
     res.result(boost::beast::http::status::bad_request);
     addMessageToErrorJson(res.jsonValue, resourceAtUriInUnknownFormat(arg1));
@@ -800,21 +807,23 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json resetRequired(const std::string& arg1, const std::string& arg2)
+nlohmann::json resetRequired(const boost::urls::url_view& arg1,
+                             const std::string& arg2)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.ResetRequired"},
         {"Message", "In order to complete the operation, a component reset is "
                     "required with the Reset action URI '" +
-                        arg1 + "' and ResetType '" + arg2 + "'."},
-        {"MessageArgs", {arg1, arg2}},
+                        url + "' and ResetType '" + arg2 + "'."},
+        {"MessageArgs", {url, arg2}},
         {"MessageSeverity", "Warning"},
         {"Resolution",
          "Perform the required Reset action on the specified component."}};
 }
 
-void resetRequired(crow::Response& res, const std::string& arg1,
+void resetRequired(crow::Response& res, const boost::urls::url_view& arg1,
                    const std::string& arg2)
 {
     res.result(boost::beast::http::status::bad_request);
@@ -939,20 +948,22 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json resourceCreationConflict(const std::string& arg1)
+nlohmann::json resourceCreationConflict(const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.ResourceCreationConflict"},
         {"Message", "The resource could not be created.  The service has a "
                     "resource at URI '" +
-                        arg1 + "' that conflicts with the creation request."},
-        {"MessageArgs", {arg1}},
+                        url + "' that conflicts with the creation request."},
+        {"MessageArgs", {url}},
         {"MessageSeverity", "Warning"},
         {"Resolution", "No resolution is required."}};
 }
 
-void resourceCreationConflict(crow::Response& res, const std::string& arg1)
+void resourceCreationConflict(crow::Response& res,
+                              const boost::urls::url_view& arg1)
 {
     res.result(boost::beast::http::status::bad_request);
     addMessageToErrorJson(res.jsonValue, resourceCreationConflict(arg1));
@@ -1153,22 +1164,24 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json couldNotEstablishConnection(const std::string& arg1)
+nlohmann::json couldNotEstablishConnection(const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.CouldNotEstablishConnection"},
         {"Message",
-         "The service failed to establish a connection with the URI " + arg1 +
+         "The service failed to establish a connection with the URI " + url +
              "."},
-        {"MessageArgs", {arg1}},
+        {"MessageArgs", {url}},
         {"MessageSeverity", "Critical"},
         {"Resolution",
          "Ensure that the URI contains a valid and reachable node name, "
          "protocol information and other URI components."}};
 }
 
-void couldNotEstablishConnection(crow::Response& res, const std::string& arg1)
+void couldNotEstablishConnection(crow::Response& res,
+                                 const boost::urls::url_view& arg1)
 {
     res.result(boost::beast::http::status::not_found);
     addMessageToErrorJson(res.jsonValue, couldNotEstablishConnection(arg1));
@@ -1326,21 +1339,23 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json sourceDoesNotSupportProtocol(const std::string& arg1,
+nlohmann::json sourceDoesNotSupportProtocol(const boost::urls::url_view& arg1,
                                             const std::string& arg2)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.SourceDoesNotSupportProtocol"},
-        {"Message", "The other end of the connection at " + arg1 +
+        {"Message", "The other end of the connection at " + url +
                         " does not support the specified protocol " + arg2 +
                         "."},
-        {"MessageArgs", {arg1, arg2}},
+        {"MessageArgs", {url, arg2}},
         {"MessageSeverity", "Critical"},
         {"Resolution", "Change protocols or URIs. "}};
 }
 
-void sourceDoesNotSupportProtocol(crow::Response& res, const std::string& arg1,
+void sourceDoesNotSupportProtocol(crow::Response& res,
+                                  const boost::urls::url_view& arg1,
                                   const std::string& arg2)
 {
     res.result(boost::beast::http::status::bad_request);
@@ -1378,20 +1393,21 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json accessDenied(const std::string& arg1)
+nlohmann::json accessDenied(const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.AccessDenied"},
-        {"Message", "While attempting to establish a connection to " + arg1 +
+        {"Message", "While attempting to establish a connection to " + url +
                         ", the service denied access."},
-        {"MessageArgs", {arg1}},
+        {"MessageArgs", {url}},
         {"MessageSeverity", "Critical"},
         {"Resolution", "Attempt to ensure that the URI is correct and that "
                        "the service has the appropriate credentials."}};
 }
 
-void accessDenied(crow::Response& res, const std::string& arg1)
+void accessDenied(crow::Response& res, const boost::urls::url_view& arg1)
 {
     res.result(boost::beast::http::status::forbidden);
     addMessageToErrorJson(res.jsonValue, accessDenied(arg1));
@@ -1610,20 +1626,21 @@
  * See header file for more information
  * @endinternal
  */
-nlohmann::json invalidObject(const std::string& arg1)
+nlohmann::json invalidObject(const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     return nlohmann::json{
         {"@odata.type", "#Message.v1_1_1.Message"},
         {"MessageId", "Base.1.8.1.InvalidObject"},
-        {"Message", "The object at " + arg1 + " is invalid."},
-        {"MessageArgs", {arg1}},
+        {"Message", "The object at " + url + " is invalid."},
+        {"MessageArgs", {url}},
         {"MessageSeverity", "Critical"},
         {"Resolution",
          "Either the object is malformed or the URI is not correct.  "
          "Correct the condition and resubmit the request if it failed."}};
 }
 
-void invalidObject(crow::Response& res, const std::string& arg1)
+void invalidObject(crow::Response& res, const boost::urls::url_view& arg1)
 {
     res.result(boost::beast::http::status::bad_request);
     addMessageToErrorJson(res.jsonValue, invalidObject(arg1));
@@ -2106,8 +2123,10 @@
  * See header file for more information
  * @endinternal
  */
-void passwordChangeRequired(crow::Response& res, const std::string& arg1)
+void passwordChangeRequired(crow::Response& res,
+                            const boost::urls::url_view& arg1)
 {
+    std::string url(arg1.data(), arg1.size());
     messages::addMessageToJsonRoot(
         res.jsonValue,
         nlohmann::json{
@@ -2117,8 +2136,8 @@
                         "changed before access is granted.  PATCH the "
                         "'Password' property for this account located at "
                         "the target URI '" +
-                            arg1 + "' to complete this process."},
-            {"MessageArgs", {arg1}},
+                            url + "' to complete this process."},
+            {"MessageArgs", {url}},
             {"MessageSeverity", "Critical"},
             {"Resolution", "Change the password for this account using "
                            "a PATCH to the 'Password' property at the URI "