Skip to content

Commit

Permalink
http: http status classification
Browse files Browse the repository at this point in the history
Add `status_class` enum for possible http code groups (classes) and a function `classify_status` to get code's classification. Intended for general usage to prevent code like `if (http_code >= XXX && http_code < YYY)`
  • Loading branch information
kreuzerkrieg authored and avikivity committed Oct 20, 2024
1 parent 15a82e1 commit 14a59f3
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
32 changes: 32 additions & 0 deletions include/seastar/http/reply.hh
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,38 @@ struct reply {
network_connect_timeout = 599, //!< network_connect_timeout
} _status;

/**
* HTTP status classes
* See https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
*
* 1xx: Informational - Request received, continuing process
* 2xx: Success - The action was successfully received, understood, and accepted
* 3xx: Redirection - Further action must be taken in order to complete the request
* 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
* 5xx: Server Error - The server failed to fulfill an apparently valid request
*/
enum class status_class : uint8_t {
informational = 1,
success = 2,
redirection = 3,
client_error = 4,
server_error = 5,
unclassified
};

/**
* Classify http status
* @param http_status the http status \ref status_type
* @return one of the \ref status_class values
*/
static constexpr status_class classify_status(status_type http_status) {
auto sc = static_cast<std::underlying_type_t<status_type>>(http_status) / 100;
if (sc < 1 || sc > 5) [[unlikely]] {
return status_class::unclassified;
}
return static_cast<status_class>(sc);
}

/**
* The headers to be included in the reply.
*/
Expand Down
55 changes: 55 additions & 0 deletions tests/unit/httpd_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1831,3 +1831,58 @@ BOOST_AUTO_TEST_CASE(test_path_decode_changed) {
auto expected_chars = seastar::sstring{" "};
BOOST_REQUIRE_EQUAL(result, expected_chars);
}

namespace seastar::http {
std::ostream& boost_test_print_type(std::ostream& os, reply::status_class sc) {
constexpr std::string_view status_strings[] {
"1xx: Informational",
"2xx: Success",
"3xx: Redirection",
"4xx: Client Error",
"5xx: Server Error",
"Unclassified"
};
auto status = static_cast<std::underlying_type_t<reply::status_class>>(sc) - 1u;
if (status < std::size(status_strings)) {
return os << status_strings[status];
}
return os << "Unclassified";
}
} // namespace seastar::http

BOOST_AUTO_TEST_CASE(test_http_status_classification) {
size_t informational = 0;
size_t success = 0;
size_t redirection = 0;
size_t client_error = 0;
size_t server_error = 0;
size_t unclassified = 0;
for (auto i = -100; i < 700; ++i) {
auto classification = http::reply::classify_status(static_cast<http::reply::status_type>(i));
if (i >= 100 && i < 200) {
++informational;
BOOST_REQUIRE_EQUAL(classification, http::reply::status_class::informational);
} else if (i >= 200 && i < 300) {
++success;
BOOST_REQUIRE_EQUAL(classification, http::reply::status_class::success);
} else if (i >= 300 && i < 400) {
++redirection;
BOOST_REQUIRE_EQUAL(classification, http::reply::status_class::redirection);
} else if (i >= 400 && i < 500) {
++client_error;
BOOST_REQUIRE_EQUAL(classification, http::reply::status_class::client_error);
} else if (i >= 500 && i < 600) {
++server_error;
BOOST_REQUIRE_EQUAL(classification, http::reply::status_class::server_error);
} else {
++unclassified;
BOOST_REQUIRE_EQUAL(classification, http::reply::status_class::unclassified);
}
}
BOOST_REQUIRE_EQUAL(informational, 100);
BOOST_REQUIRE_EQUAL(success, 100);
BOOST_REQUIRE_EQUAL(redirection, 100);
BOOST_REQUIRE_EQUAL(client_error, 100);
BOOST_REQUIRE_EQUAL(server_error, 100);
BOOST_REQUIRE_EQUAL(unclassified, 300);
}

0 comments on commit 14a59f3

Please sign in to comment.