Add Method Not Allowed (405) handler

Similar to the 404 handler, add a 405 handler for registering custom 405
handlers for a given tree.  The primary use case is for protocols like
redfish that support specific messages for 405 handlers that don't have
an empty body.

Tested: Unit tests pass.

PATCH /redfish/v1 returns 405 Method Not Allowed
POST /redfish/v1/Chassis returns 405 Method Not Allowed
POST /redfish/v1/Chassis/foo returns 405 Method Not Allowed
PATCH /redfish/v1/foo/bar returns 404 Not Found
GET /redfish/v1 returns ServiceRoot
GET /redfish/v1/Chassis returns Chassis collection

Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ib0afd23d46bb5b88f89cf1e3f4e0606a48ae47ca
Signed-off-by: Carson Labrado <clabrado@google.com>
diff --git a/http/ut/router_test.cpp b/http/ut/router_test.cpp
index b43b659..9b5d9be 100644
--- a/http/ut/router_test.cpp
+++ b/http/ut/router_test.cpp
@@ -90,5 +90,37 @@
     }
     EXPECT_TRUE(notFoundCalled);
 }
+
+TEST(Router, 405)
+{
+    // Callback handler that does nothing
+    auto nullCallback = [](const Request&,
+                           const std::shared_ptr<bmcweb::AsyncResp>&) {};
+    bool called = false;
+    auto notAllowedCallback =
+        [&called](const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) {
+        called = true;
+    };
+
+    Router router;
+    std::error_code ec;
+
+    constexpr const std::string_view url = "/foo/bar";
+
+    Request req{{boost::beast::http::verb::patch, url, 11}, ec};
+
+    router.newRuleTagged<getParameterTag(url)>(std::string(url))
+        .methods(boost::beast::http::verb::get)(nullCallback);
+    router.newRuleTagged<getParameterTag(url)>("/foo/<path>")
+        .methodNotAllowed()(notAllowedCallback);
+    router.validate();
+    {
+        std::shared_ptr<bmcweb::AsyncResp> asyncResp =
+            std::make_shared<bmcweb::AsyncResp>();
+
+        router.handle(req, asyncResp);
+    }
+    EXPECT_TRUE(called);
+}
 } // namespace
 } // namespace crow