mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-25 12:14:41 +00:00
Simplify get_bearer_token_auth and table-drive its test
Drop the now-redundant has_header guard (get_header_value already returns "" for a missing header, which the length check rejects), name the "Bearer " prefix once, and cite RFC 9110 to match the file's convention. Convert the regression test to the table-driven form used elsewhere in test.cc and move it out of the middle of GetHeaderValueTest so that suite stays contiguous.
This commit is contained in:
1 parent
2a068def54
commit
70b49d50bd
2 files changed
+29
-40
No files matched your search
@@ -10458,18 +10458,15 @@ inline bool set_socket_opt(socket_t sock, int level, int optname, int optval) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline std::string get_bearer_token_auth(const Request &req) {
|
inline std::string get_bearer_token_auth(const Request &req) {
|
||||||
if (req.has_header("Authorization")) {
|
// The auth scheme is case-insensitive (RFC 9110 11.1), and a value shorter
|
||||||
constexpr auto bearer_header_prefix_len = detail::str_len("Bearer ");
|
// than the prefix carries no token.
|
||||||
auto value = req.get_header_value("Authorization");
|
constexpr const char bearer_prefix[] = "Bearer ";
|
||||||
// Only strip the prefix when the value actually carries the "Bearer "
|
constexpr auto bearer_prefix_len = detail::str_len(bearer_prefix);
|
||||||
// scheme (case-insensitive per RFC 7235). Without this the fixed-length
|
auto value = req.get_header_value("Authorization");
|
||||||
// substr throws out_of_range on a value shorter than the prefix, and a
|
if (value.size() >= bearer_prefix_len &&
|
||||||
// different scheme (e.g. "Basic ...") is mistaken for a bearer token.
|
detail::case_ignore::equal(value.substr(0, bearer_prefix_len),
|
||||||
if (value.size() >= bearer_header_prefix_len &&
|
bearer_prefix)) {
|
||||||
detail::case_ignore::equal(value.substr(0, bearer_header_prefix_len),
|
return value.substr(bearer_prefix_len);
|
||||||
"Bearer ")) {
|
|
||||||
return value.substr(bearer_header_prefix_len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-28
@@ -1560,34 +1560,6 @@ TEST(GetHeaderValueTest, RegularInvalidValueInt) {
|
|||||||
EXPECT_TRUE(is_invalid_value);
|
EXPECT_TRUE(is_invalid_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BearerTokenAuthTest, SchemeValidation) {
|
|
||||||
// A value shorter than "Bearer " must not throw from the fixed-length
|
|
||||||
// substr, and a non-Bearer scheme must not be reported as a token.
|
|
||||||
{
|
|
||||||
Request req;
|
|
||||||
req.set_header("Authorization", "x");
|
|
||||||
EXPECT_EQ("", get_bearer_token_auth(req));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Request req;
|
|
||||||
req.set_header("Authorization", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
|
|
||||||
EXPECT_EQ("", get_bearer_token_auth(req));
|
|
||||||
}
|
|
||||||
|
|
||||||
// A well-formed header still yields the token; the scheme is
|
|
||||||
// case-insensitive.
|
|
||||||
{
|
|
||||||
Request req;
|
|
||||||
req.set_header("Authorization", "Bearer abc123");
|
|
||||||
EXPECT_EQ("abc123", get_bearer_token_auth(req));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Request req;
|
|
||||||
req.set_header("Authorization", "bearer abc123");
|
|
||||||
EXPECT_EQ("abc123", get_bearer_token_auth(req));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(GetHeaderValueTest, OutOfRangeValueInt) {
|
TEST(GetHeaderValueTest, OutOfRangeValueInt) {
|
||||||
// An all-digit value that overflows size_t must be reported as invalid, not
|
// An all-digit value that overflows size_t must be reported as invalid, not
|
||||||
// silently saturated/truncated: parsing at size_t width would otherwise wrap
|
// silently saturated/truncated: parsing at size_t width would otherwise wrap
|
||||||
@@ -1646,6 +1618,26 @@ TEST(GetHeaderValueTest, Range) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BearerTokenAuthTest, SchemeValidation) {
|
||||||
|
// A value shorter than "Bearer " must not throw from the fixed-length
|
||||||
|
// substr, and a non-Bearer scheme must not be reported as a token.
|
||||||
|
struct {
|
||||||
|
const char *value;
|
||||||
|
const char *expected;
|
||||||
|
} cases[] = {
|
||||||
|
{"x", ""},
|
||||||
|
{"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", ""},
|
||||||
|
{"Bearer abc123", "abc123"},
|
||||||
|
{"bearer abc123", "abc123"}, // scheme match is case-insensitive
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &c : cases) {
|
||||||
|
Request req;
|
||||||
|
req.set_header("Authorization", c.value);
|
||||||
|
EXPECT_EQ(c.expected, get_bearer_token_auth(req)) << "value: " << c.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(HeadersOrderTest, DuplicateFieldsKeepInsertionOrder) {
|
TEST(HeadersOrderTest, DuplicateFieldsKeepInsertionOrder) {
|
||||||
// RFC 9110 5.3: the order of fields sharing a name is significant. This used
|
// RFC 9110 5.3: the order of fields sharing a name is significant. This used
|
||||||
// to depend on the standard library (libstdc++ handed back duplicates in
|
// to depend on the standard library (libstdc++ handed back duplicates in
|
||||||
|
|||||||
Reference in new issue
Block a user