Fix redfish response for unknown method
Redfish protocol validator recently added a new test to check for
invalid methods[1] and expect a valid redfish response.
bmcweb will return the correct response if the HTTP method is known, but
returns 404 for unknown methods.
This commit implements support for returning the proper code for
completely unknown methods.
Tested: Redfish protocol validator passes.
```
curl -k -X METHODNOTEXIST "https://192.168.7.2/redfish/v1"
curl --http1.1 -k -X METHODNOTEXIST "https://192.168.7.2/redfish/v1"
```
works for both HTTP1 and HTTP2.
[1] https://github.com/DMTF/Redfish-Protocol-Validator/commit/2476e126b818f040c7231de3e9dc4df93ee636a1
Change-Id: Id7436345042bd387d7a7b706acd06afda744ddc4
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/http/http2_connection.hpp b/http/http2_connection.hpp
index 1dcf87a..be73991 100644
--- a/http/http2_connection.hpp
+++ b/http/http2_connection.hpp
@@ -438,8 +438,7 @@
if (verb == boost::beast::http::verb::unknown)
{
BMCWEB_LOG_ERROR("Unknown http verb {}", valueSv);
- close();
- return -1;
+ verb = boost::beast::http::verb::trace;
}
thisReq.method(verb);
}
diff --git a/http/http_request.hpp b/http/http_request.hpp
index 55387d4..7cf2842 100644
--- a/http/http_request.hpp
+++ b/http/http_request.hpp
@@ -75,11 +75,17 @@
{
return req.method();
}
+
void method(boost::beast::http::verb verb)
{
req.method(verb);
}
+ std::string_view methodString()
+ {
+ return req.method_string();
+ }
+
std::string_view getHeaderValue(std::string_view key) const
{
return req[key];
diff --git a/http/routing.hpp b/http/routing.hpp
index 6f42d22..85bc626 100644
--- a/http/routing.hpp
+++ b/http/routing.hpp
@@ -521,12 +521,6 @@
{
FindRouteResponse findRoute;
- std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
- if (!verb)
- {
- return findRoute;
- }
- size_t reqMethodIndex = static_cast<size_t>(*verb);
// Check to see if this url exists at any verb
for (size_t perMethodIndex = 0; perMethodIndex <= maxVerbIndex;
perMethodIndex++)
@@ -546,11 +540,26 @@
}
HttpVerb thisVerb = static_cast<HttpVerb>(perMethodIndex);
findRoute.allowHeader += httpVerbToString(thisVerb);
- if (perMethodIndex == reqMethodIndex)
- {
- findRoute.route = route;
- }
}
+
+ std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
+ if (!verb)
+ {
+ return findRoute;
+ }
+ size_t reqMethodIndex = static_cast<size_t>(*verb);
+ if (reqMethodIndex >= perMethods.size())
+ {
+ return findRoute;
+ }
+
+ FindRoute route = findRouteByPerMethod(req.url().encoded_path(),
+ perMethods[reqMethodIndex]);
+ if (route.rule != nullptr)
+ {
+ findRoute.route = route;
+ }
+
return findRoute;
}
@@ -595,13 +604,6 @@
void handle(const std::shared_ptr<Request>& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
- std::optional<HttpVerb> verb = httpVerbFromBoost(req->method());
- if (!verb || static_cast<size_t>(*verb) >= perMethods.size())
- {
- asyncResp->res.result(boost::beast::http::status::not_found);
- return;
- }
-
FindRouteResponse foundRoute = findRoute(*req);
if (foundRoute.route.rule == nullptr)
@@ -648,7 +650,7 @@
std::vector<std::string> params = std::move(foundRoute.route.params);
BMCWEB_LOG_DEBUG("Matched rule '{}' {} / {}", rule.rule,
- static_cast<uint32_t>(*verb), rule.getMethods());
+ req->methodString(), rule.getMethods());
if (req->session == nullptr)
{