yhirose 6 years ago
parent
commit
eaafa5d55c
3 changed files with 57 additions and 7 deletions
  1. 16 5
      README.md
  2. 38 0
      httplib.h
  3. 3 2
      test/test.cc

+ 16 - 5
README.md

@@ -195,15 +195,26 @@ std::shared_ptr<httplib::Response> res =
 
 This feature was contributed by [underscorediscovery](https://github.com/yhirose/cpp-httplib/pull/23).
 
-### Range
+### Basic Authentication
 
 ```cpp
-httplib::Client cli("httpbin.org", 80);
+httplib::Client cli("httplib.org");
+
+auto res = cli.Get("/basic-auth/hello/world", {
+  httplib::make_basic_authentication_header("hello", "world")
+});
+// res->status should be 200
+// res->body should be "{\n  \"authenticated\": true, \n  \"user\": \"hello\"\n}\n".
+```
 
-// 'Range: bytes=1-10'
-httplib::Headers headers = { httplib::make_range_header(1, 10) };
+### Range
+
+```cpp
+httplib::Client cli("httpbin.org");
 
-auto res = cli.Get("/range/32", headers);
+auto res = cli.Get("/range/32", {
+  httplib::make_range_header(1, 10) // 'Range: bytes=1-10'
+});
 // res->status should be 206.
 // res->body should be "bcdefghijk".
 ```

+ 38 - 0
httplib.h

@@ -529,6 +529,38 @@ inline size_t to_utf8(int code, char *buff) {
   return 0;
 }
 
+// NOTE: This code came up with the following stackoverflow post:
+// https://stackoverflow.com/questions/180947/base64-decode-snippet-in-c
+inline std::string base64_encode(const std::string &in) {
+  static const auto lookup =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  std::string out;
+  out.reserve(in.size());
+
+  int val = 0;
+  int valb = -6;
+
+  for (uint8_t c : in) {
+    val = (val << 8) + c;
+    valb += 8;
+    while (valb >= 0) {
+      out.push_back(lookup[(val >> valb) & 0x3F]);
+      valb -= 6;
+    }
+  }
+
+  if (valb > -6) {
+    out.push_back(lookup[((val << 8) >> (valb + 8)) & 0x3F]);
+  }
+
+  while (out.size() % 4) {
+    out.push_back('=');
+  }
+
+  return out;
+}
+
 inline bool is_file(const std::string &path) {
   struct stat st;
   return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode);
@@ -1439,6 +1471,12 @@ inline std::pair<std::string, std::string> make_range_header(uint64_t value,
   return std::make_pair("Range", field);
 }
 
+
+inline std::pair<std::string, std::string> 
+make_basic_authentication_header(const std::string& username, const std::string& password) {
+  auto field = "Basic " + detail::base64_encode(username + ":" + password);
+  return std::make_pair("Authorization", field);
+}
 // Request implementation
 inline bool Request::has_header(const char *key) const {
   return detail::has_header(headers, key);

+ 3 - 2
test/test.cc

@@ -327,8 +327,9 @@ TEST(BaseAuthTest, FromHTTPWatch) {
   }
 
   {
-    httplib::Headers headers = {{"Authorization", "Basic aGVsbG86d29ybGQ="}};
-    auto res = cli.Get("/basic-auth/hello/world", headers);
+    auto res = cli.Get("/basic-auth/hello/world", {
+      httplib::make_basic_authentication_header("hello", "world")
+    });
     ASSERT_TRUE(res != nullptr);
     EXPECT_EQ(res->body,
               "{\n  \"authenticated\": true, \n  \"user\": \"hello\"\n}\n");