Parcourir la source

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.
yhirose il y a 6 jours
Parent
commit
70b49d50bd
2 fichiers modifiés avec 29 ajouts et 40 suppressions
  1. 9 12
      httplib.h
  2. 20 28
      test/test.cc

+ 9 - 12
httplib.h

@@ -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) {
-  if (req.has_header("Authorization")) {
-    constexpr auto bearer_header_prefix_len = detail::str_len("Bearer ");
-    auto value = req.get_header_value("Authorization");
-    // Only strip the prefix when the value actually carries the "Bearer "
-    // scheme (case-insensitive per RFC 7235). Without this the fixed-length
-    // substr throws out_of_range on a value shorter than the prefix, and a
-    // different scheme (e.g. "Basic ...") is mistaken for a bearer token.
-    if (value.size() >= bearer_header_prefix_len &&
-        detail::case_ignore::equal(value.substr(0, bearer_header_prefix_len),
-                                   "Bearer ")) {
-      return value.substr(bearer_header_prefix_len);
-    }
+  // The auth scheme is case-insensitive (RFC 9110 11.1), and a value shorter
+  // than the prefix carries no token.
+  constexpr const char bearer_prefix[] = "Bearer ";
+  constexpr auto bearer_prefix_len = detail::str_len(bearer_prefix);
+  auto value = req.get_header_value("Authorization");
+  if (value.size() >= bearer_prefix_len &&
+      detail::case_ignore::equal(value.substr(0, bearer_prefix_len),
+                                 bearer_prefix)) {
+    return value.substr(bearer_prefix_len);
   }
   return "";
 }

+ 20 - 28
test/test.cc

@@ -1560,34 +1560,6 @@ TEST(GetHeaderValueTest, RegularInvalidValueInt) {
   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) {
   // 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
@@ -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) {
   // 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