Move /bus/system/<str>/<path> POST to method

Per the reorganization we've done elsewhere, move this large lambda
function to simplify it.

Tested: Code move only.  Code compiles.

Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ib0586b34809167120bdc127868706ac517db4474
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index 042f193..4f4bd71 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -2102,6 +2102,321 @@
                      methodNotAllowedDesc, methodNotAllowedMsg);
 }
 
+inline void
+    handleBusSystemPost(const crow::Request& req,
+                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                        const std::string& processName,
+                        const std::string& requestedPath)
+{
+    std::vector<std::string> strs;
+    boost::split(strs, requestedPath, boost::is_any_of("/"));
+    std::string objectPath;
+    std::string interfaceName;
+    std::string methodName;
+    auto it = strs.begin();
+    if (it == strs.end())
+    {
+        objectPath = "/";
+    }
+    while (it != strs.end())
+    {
+        // Check if segment contains ".".  If it does, it must be an
+        // interface
+        if (it->find(".") != std::string::npos)
+        {
+            break;
+            // This check is necessary as the trailing slash gets
+            // parsed as part of our <path> specifier above, which
+            // causes the normal trailing backslash redirector to
+            // fail.
+        }
+        if (!it->empty())
+        {
+            objectPath += "/" + *it;
+        }
+        it++;
+    }
+    if (it != strs.end())
+    {
+        interfaceName = *it;
+        it++;
+
+        // after interface, we might have a method name
+        if (it != strs.end())
+        {
+            methodName = *it;
+            it++;
+        }
+    }
+    if (it != strs.end())
+    {
+        // if there is more levels past the method name, something
+        // went wrong, return not found
+        asyncResp->res.result(boost::beast::http::status::not_found);
+        return;
+    }
+    if (interfaceName.empty())
+    {
+        crow::connections::systemBus->async_method_call(
+            [asyncResp, processName,
+             objectPath](const boost::system::error_code ec,
+                         const std::string& introspectXml) {
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR
+                        << "Introspect call failed with error: " << ec.message()
+                        << " on process: " << processName
+                        << " path: " << objectPath << "\n";
+                    return;
+                }
+                tinyxml2::XMLDocument doc;
+
+                doc.Parse(introspectXml.c_str());
+                tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
+                if (pRoot == nullptr)
+                {
+                    BMCWEB_LOG_ERROR << "XML document failed to parse "
+                                     << processName << " " << objectPath
+                                     << "\n";
+                    asyncResp->res.jsonValue = {{"status", "XML parse error"}};
+                    asyncResp->res.result(
+                        boost::beast::http::status::internal_server_error);
+                    return;
+                }
+
+                BMCWEB_LOG_DEBUG << introspectXml;
+                asyncResp->res.jsonValue = {{"status", "ok"},
+                                            {"bus_name", processName},
+                                            {"object_path", objectPath}};
+                nlohmann::json& interfacesArray =
+                    asyncResp->res.jsonValue["interfaces"];
+                interfacesArray = nlohmann::json::array();
+                tinyxml2::XMLElement* interface =
+                    pRoot->FirstChildElement("interface");
+
+                while (interface != nullptr)
+                {
+                    const char* ifaceName = interface->Attribute("name");
+                    if (ifaceName != nullptr)
+                    {
+                        interfacesArray.push_back({{"name", ifaceName}});
+                    }
+
+                    interface = interface->NextSiblingElement("interface");
+                }
+            },
+            processName, objectPath, "org.freedesktop.DBus.Introspectable",
+            "Introspect");
+    }
+    else if (methodName.empty())
+    {
+        crow::connections::systemBus->async_method_call(
+            [asyncResp, processName, objectPath,
+             interfaceName](const boost::system::error_code ec,
+                            const std::string& introspectXml) {
+                if (ec)
+                {
+                    BMCWEB_LOG_ERROR
+                        << "Introspect call failed with error: " << ec.message()
+                        << " on process: " << processName
+                        << " path: " << objectPath << "\n";
+                    return;
+                }
+                tinyxml2::XMLDocument doc;
+
+                doc.Parse(introspectXml.data(), introspectXml.size());
+                tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
+                if (pRoot == nullptr)
+                {
+                    BMCWEB_LOG_ERROR << "XML document failed to parse "
+                                     << processName << " " << objectPath
+                                     << "\n";
+                    asyncResp->res.result(
+                        boost::beast::http::status::internal_server_error);
+                    return;
+                }
+                asyncResp->res.jsonValue = {{"status", "ok"},
+                                            {"bus_name", processName},
+                                            {"interface", interfaceName},
+                                            {"object_path", objectPath}};
+
+                nlohmann::json& methodsArray =
+                    asyncResp->res.jsonValue["methods"];
+                methodsArray = nlohmann::json::array();
+
+                nlohmann::json& signalsArray =
+                    asyncResp->res.jsonValue["signals"];
+                signalsArray = nlohmann::json::array();
+
+                nlohmann::json& propertiesObj =
+                    asyncResp->res.jsonValue["properties"];
+                propertiesObj = nlohmann::json::object();
+
+                // if we know we're the only call, build the
+                // json directly
+                tinyxml2::XMLElement* interface =
+                    pRoot->FirstChildElement("interface");
+                while (interface != nullptr)
+                {
+                    const char* ifaceName = interface->Attribute("name");
+
+                    if (ifaceName != nullptr && ifaceName == interfaceName)
+                    {
+                        break;
+                    }
+
+                    interface = interface->NextSiblingElement("interface");
+                }
+                if (interface == nullptr)
+                {
+                    // if we got to the end of the list and
+                    // never found a match, throw 404
+                    asyncResp->res.result(
+                        boost::beast::http::status::not_found);
+                    return;
+                }
+
+                tinyxml2::XMLElement* methods =
+                    interface->FirstChildElement("method");
+                while (methods != nullptr)
+                {
+                    nlohmann::json argsArray = nlohmann::json::array();
+                    tinyxml2::XMLElement* arg =
+                        methods->FirstChildElement("arg");
+                    while (arg != nullptr)
+                    {
+                        nlohmann::json thisArg;
+                        for (const char* fieldName : std::array<const char*, 3>{
+                                 "name", "direction", "type"})
+                        {
+                            const char* fieldValue = arg->Attribute(fieldName);
+                            if (fieldValue != nullptr)
+                            {
+                                thisArg[fieldName] = fieldValue;
+                            }
+                        }
+                        argsArray.push_back(std::move(thisArg));
+                        arg = arg->NextSiblingElement("arg");
+                    }
+
+                    const char* name = methods->Attribute("name");
+                    if (name != nullptr)
+                    {
+                        std::string uri;
+                        uri.reserve(14 + processName.size() +
+                                    objectPath.size() + interfaceName.size() +
+                                    strlen(name));
+                        uri += "/bus/system/";
+                        uri += processName;
+                        uri += objectPath;
+                        uri += "/";
+                        uri += interfaceName;
+                        uri += "/";
+                        uri += name;
+                        methodsArray.push_back({{"name", name},
+                                                {"uri", std::move(uri)},
+                                                {"args", argsArray}});
+                    }
+                    methods = methods->NextSiblingElement("method");
+                }
+                tinyxml2::XMLElement* signals =
+                    interface->FirstChildElement("signal");
+                while (signals != nullptr)
+                {
+                    nlohmann::json argsArray = nlohmann::json::array();
+
+                    tinyxml2::XMLElement* arg =
+                        signals->FirstChildElement("arg");
+                    while (arg != nullptr)
+                    {
+                        const char* name = arg->Attribute("name");
+                        const char* type = arg->Attribute("type");
+                        if (name != nullptr && type != nullptr)
+                        {
+                            argsArray.push_back({
+                                {"name", name},
+                                {"type", type},
+                            });
+                        }
+                        arg = arg->NextSiblingElement("arg");
+                    }
+                    const char* name = signals->Attribute("name");
+                    if (name != nullptr)
+                    {
+                        signalsArray.push_back(
+                            {{"name", name}, {"args", argsArray}});
+                    }
+
+                    signals = signals->NextSiblingElement("signal");
+                }
+
+                tinyxml2::XMLElement* property =
+                    interface->FirstChildElement("property");
+                while (property != nullptr)
+                {
+                    const char* name = property->Attribute("name");
+                    const char* type = property->Attribute("type");
+                    if (type != nullptr && name != nullptr)
+                    {
+                        sdbusplus::message::message m =
+                            crow::connections::systemBus->new_method_call(
+                                processName.c_str(), objectPath.c_str(),
+                                "org.freedesktop."
+                                "DBus."
+                                "Properties",
+                                "Get");
+                        m.append(interfaceName, name);
+                        nlohmann::json& propertyItem = propertiesObj[name];
+                        crow::connections::systemBus->async_send(
+                            m, [&propertyItem,
+                                asyncResp](boost::system::error_code& e,
+                                           sdbusplus::message::message& msg) {
+                                if (e)
+                                {
+                                    return;
+                                }
+
+                                convertDBusToJSON("v", msg, propertyItem);
+                            });
+                    }
+                    property = property->NextSiblingElement("property");
+                }
+            },
+            processName, objectPath, "org.freedesktop.DBus.Introspectable",
+            "Introspect");
+    }
+    else
+    {
+        if (req.method() != boost::beast::http::verb::post)
+        {
+            asyncResp->res.result(boost::beast::http::status::not_found);
+            return;
+        }
+
+        nlohmann::json requestDbusData =
+            nlohmann::json::parse(req.body, nullptr, false);
+
+        if (requestDbusData.is_discarded())
+        {
+            asyncResp->res.result(boost::beast::http::status::bad_request);
+            return;
+        }
+        if (!requestDbusData.is_array())
+        {
+            asyncResp->res.result(boost::beast::http::status::bad_request);
+            return;
+        }
+        auto transaction =
+            std::make_shared<InProgressActionData>(asyncResp->res);
+
+        transaction->path = objectPath;
+        transaction->methodName = methodName;
+        transaction->arguments = std::move(requestDbusData);
+
+        findActionOnInterface(transaction, processName);
+    }
+}
+
 inline void requestRoutes(App& app)
 {
     BMCWEB_ROUTE(app, "/bus/")
@@ -2275,351 +2590,8 @@
 
     BMCWEB_ROUTE(app, "/bus/system/<str>/<path>")
         .privileges({{"ConfigureComponents", "ConfigureManager"}})
-        .methods(boost::beast::http::verb::get, boost::beast::http::verb::post)(
-            [](const crow::Request& req,
-               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-               const std::string& processName,
-               const std::string& requestedPath) {
-                std::vector<std::string> strs;
-                boost::split(strs, requestedPath, boost::is_any_of("/"));
-                std::string objectPath;
-                std::string interfaceName;
-                std::string methodName;
-                auto it = strs.begin();
-                if (it == strs.end())
-                {
-                    objectPath = "/";
-                }
-                while (it != strs.end())
-                {
-                    // Check if segment contains ".".  If it does, it must be an
-                    // interface
-                    if (it->find(".") != std::string::npos)
-                    {
-                        break;
-                        // This check is necessary as the trailing slash gets
-                        // parsed as part of our <path> specifier above, which
-                        // causes the normal trailing backslash redirector to
-                        // fail.
-                    }
-                    if (!it->empty())
-                    {
-                        objectPath += "/" + *it;
-                    }
-                    it++;
-                }
-                if (it != strs.end())
-                {
-                    interfaceName = *it;
-                    it++;
-
-                    // after interface, we might have a method name
-                    if (it != strs.end())
-                    {
-                        methodName = *it;
-                        it++;
-                    }
-                }
-                if (it != strs.end())
-                {
-                    // if there is more levels past the method name, something
-                    // went wrong, return not found
-                    asyncResp->res.result(
-                        boost::beast::http::status::not_found);
-                    return;
-                }
-                if (interfaceName.empty())
-                {
-                    crow::connections::systemBus->async_method_call(
-                        [asyncResp, processName,
-                         objectPath](const boost::system::error_code ec,
-                                     const std::string& introspectXml) {
-                            if (ec)
-                            {
-                                BMCWEB_LOG_ERROR
-                                    << "Introspect call failed with error: "
-                                    << ec.message()
-                                    << " on process: " << processName
-                                    << " path: " << objectPath << "\n";
-                                return;
-                            }
-                            tinyxml2::XMLDocument doc;
-
-                            doc.Parse(introspectXml.c_str());
-                            tinyxml2::XMLNode* pRoot =
-                                doc.FirstChildElement("node");
-                            if (pRoot == nullptr)
-                            {
-                                BMCWEB_LOG_ERROR
-                                    << "XML document failed to parse "
-                                    << processName << " " << objectPath << "\n";
-                                asyncResp->res.jsonValue = {
-                                    {"status", "XML parse error"}};
-                                asyncResp->res.result(
-                                    boost::beast::http::status::
-                                        internal_server_error);
-                                return;
-                            }
-
-                            BMCWEB_LOG_DEBUG << introspectXml;
-                            asyncResp->res.jsonValue = {
-                                {"status", "ok"},
-                                {"bus_name", processName},
-                                {"object_path", objectPath}};
-                            nlohmann::json& interfacesArray =
-                                asyncResp->res.jsonValue["interfaces"];
-                            interfacesArray = nlohmann::json::array();
-                            tinyxml2::XMLElement* interface =
-                                pRoot->FirstChildElement("interface");
-
-                            while (interface != nullptr)
-                            {
-                                const char* ifaceName =
-                                    interface->Attribute("name");
-                                if (ifaceName != nullptr)
-                                {
-                                    interfacesArray.push_back(
-                                        {{"name", ifaceName}});
-                                }
-
-                                interface =
-                                    interface->NextSiblingElement("interface");
-                            }
-                        },
-                        processName, objectPath,
-                        "org.freedesktop.DBus.Introspectable", "Introspect");
-                }
-                else if (methodName.empty())
-                {
-                    crow::connections::systemBus->async_method_call(
-                        [asyncResp, processName, objectPath,
-                         interfaceName](const boost::system::error_code ec,
-                                        const std::string& introspectXml) {
-                            if (ec)
-                            {
-                                BMCWEB_LOG_ERROR
-                                    << "Introspect call failed with error: "
-                                    << ec.message()
-                                    << " on process: " << processName
-                                    << " path: " << objectPath << "\n";
-                                return;
-                            }
-                            tinyxml2::XMLDocument doc;
-
-                            doc.Parse(introspectXml.data(),
-                                      introspectXml.size());
-                            tinyxml2::XMLNode* pRoot =
-                                doc.FirstChildElement("node");
-                            if (pRoot == nullptr)
-                            {
-                                BMCWEB_LOG_ERROR
-                                    << "XML document failed to parse "
-                                    << processName << " " << objectPath << "\n";
-                                asyncResp->res.result(
-                                    boost::beast::http::status::
-                                        internal_server_error);
-                                return;
-                            }
-                            asyncResp->res.jsonValue = {
-                                {"status", "ok"},
-                                {"bus_name", processName},
-                                {"interface", interfaceName},
-                                {"object_path", objectPath}};
-
-                            nlohmann::json& methodsArray =
-                                asyncResp->res.jsonValue["methods"];
-                            methodsArray = nlohmann::json::array();
-
-                            nlohmann::json& signalsArray =
-                                asyncResp->res.jsonValue["signals"];
-                            signalsArray = nlohmann::json::array();
-
-                            nlohmann::json& propertiesObj =
-                                asyncResp->res.jsonValue["properties"];
-                            propertiesObj = nlohmann::json::object();
-
-                            // if we know we're the only call, build the
-                            // json directly
-                            tinyxml2::XMLElement* interface =
-                                pRoot->FirstChildElement("interface");
-                            while (interface != nullptr)
-                            {
-                                const char* ifaceName =
-                                    interface->Attribute("name");
-
-                                if (ifaceName != nullptr &&
-                                    ifaceName == interfaceName)
-                                {
-                                    break;
-                                }
-
-                                interface =
-                                    interface->NextSiblingElement("interface");
-                            }
-                            if (interface == nullptr)
-                            {
-                                // if we got to the end of the list and
-                                // never found a match, throw 404
-                                asyncResp->res.result(
-                                    boost::beast::http::status::not_found);
-                                return;
-                            }
-
-                            tinyxml2::XMLElement* methods =
-                                interface->FirstChildElement("method");
-                            while (methods != nullptr)
-                            {
-                                nlohmann::json argsArray =
-                                    nlohmann::json::array();
-                                tinyxml2::XMLElement* arg =
-                                    methods->FirstChildElement("arg");
-                                while (arg != nullptr)
-                                {
-                                    nlohmann::json thisArg;
-                                    for (const char* fieldName :
-                                         std::array<const char*, 3>{
-                                             "name", "direction", "type"})
-                                    {
-                                        const char* fieldValue =
-                                            arg->Attribute(fieldName);
-                                        if (fieldValue != nullptr)
-                                        {
-                                            thisArg[fieldName] = fieldValue;
-                                        }
-                                    }
-                                    argsArray.push_back(std::move(thisArg));
-                                    arg = arg->NextSiblingElement("arg");
-                                }
-
-                                const char* name = methods->Attribute("name");
-                                if (name != nullptr)
-                                {
-                                    std::string uri;
-                                    uri.reserve(14 + processName.size() +
-                                                objectPath.size() +
-                                                interfaceName.size() +
-                                                strlen(name));
-                                    uri += "/bus/system/";
-                                    uri += processName;
-                                    uri += objectPath;
-                                    uri += "/";
-                                    uri += interfaceName;
-                                    uri += "/";
-                                    uri += name;
-                                    methodsArray.push_back(
-                                        {{"name", name},
-                                         {"uri", std::move(uri)},
-                                         {"args", argsArray}});
-                                }
-                                methods = methods->NextSiblingElement("method");
-                            }
-                            tinyxml2::XMLElement* signals =
-                                interface->FirstChildElement("signal");
-                            while (signals != nullptr)
-                            {
-                                nlohmann::json argsArray =
-                                    nlohmann::json::array();
-
-                                tinyxml2::XMLElement* arg =
-                                    signals->FirstChildElement("arg");
-                                while (arg != nullptr)
-                                {
-                                    const char* name = arg->Attribute("name");
-                                    const char* type = arg->Attribute("type");
-                                    if (name != nullptr && type != nullptr)
-                                    {
-                                        argsArray.push_back({
-                                            {"name", name},
-                                            {"type", type},
-                                        });
-                                    }
-                                    arg = arg->NextSiblingElement("arg");
-                                }
-                                const char* name = signals->Attribute("name");
-                                if (name != nullptr)
-                                {
-                                    signalsArray.push_back(
-                                        {{"name", name}, {"args", argsArray}});
-                                }
-
-                                signals = signals->NextSiblingElement("signal");
-                            }
-
-                            tinyxml2::XMLElement* property =
-                                interface->FirstChildElement("property");
-                            while (property != nullptr)
-                            {
-                                const char* name = property->Attribute("name");
-                                const char* type = property->Attribute("type");
-                                if (type != nullptr && name != nullptr)
-                                {
-                                    sdbusplus::message::message m =
-                                        crow::connections::systemBus
-                                            ->new_method_call(
-                                                processName.c_str(),
-                                                objectPath.c_str(),
-                                                "org.freedesktop."
-                                                "DBus."
-                                                "Properties",
-                                                "Get");
-                                    m.append(interfaceName, name);
-                                    nlohmann::json& propertyItem =
-                                        propertiesObj[name];
-                                    crow::connections::systemBus->async_send(
-                                        m,
-                                        [&propertyItem, asyncResp](
-                                            boost::system::error_code& e,
-                                            sdbusplus::message::message& msg) {
-                                            if (e)
-                                            {
-                                                return;
-                                            }
-
-                                            convertDBusToJSON("v", msg,
-                                                              propertyItem);
-                                        });
-                                }
-                                property =
-                                    property->NextSiblingElement("property");
-                            }
-                        },
-                        processName, objectPath,
-                        "org.freedesktop.DBus.Introspectable", "Introspect");
-                }
-                else
-                {
-                    if (req.method() != boost::beast::http::verb::post)
-                    {
-                        asyncResp->res.result(
-                            boost::beast::http::status::not_found);
-                        return;
-                    }
-
-                    nlohmann::json requestDbusData =
-                        nlohmann::json::parse(req.body, nullptr, false);
-
-                    if (requestDbusData.is_discarded())
-                    {
-                        asyncResp->res.result(
-                            boost::beast::http::status::bad_request);
-                        return;
-                    }
-                    if (!requestDbusData.is_array())
-                    {
-                        asyncResp->res.result(
-                            boost::beast::http::status::bad_request);
-                        return;
-                    }
-                    auto transaction =
-                        std::make_shared<InProgressActionData>(asyncResp->res);
-
-                    transaction->path = objectPath;
-                    transaction->methodName = methodName;
-                    transaction->arguments = std::move(requestDbusData);
-
-                    findActionOnInterface(transaction, processName);
-                }
-            });
+        .methods(boost::beast::http::verb::get,
+                 boost::beast::http::verb::post)(handleBusSystemPost);
 }
 } // namespace openbmc_mapper
 } // namespace crow