ソースを参照

LibHTTP: Add HTTP Basic Authentication header generation and parsing

This patch adds two new static methods to HttpRequest.
get_http_basic_authentication_header generates a "Authorization" header
from a given URL, where as parse_http_basic_authentication_header parses
an "Authorization" header into username and password.
Max Wipfli 4 年 前
コミット
1d990b3e7b

+ 34 - 2
Userland/Libraries/LibHTTP/HttpRequest.cpp

@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
+#include <AK/Base64.h>
 #include <AK/StringBuilder.h>
 #include <LibHTTP/HttpJob.h>
 #include <LibHTTP/HttpRequest.h>
@@ -57,7 +58,7 @@ ByteBuffer HttpRequest::to_raw_request() const
     builder.append("Connection: close\r\n");
     if (!m_body.is_empty()) {
         builder.appendff("Content-Length: {}\r\n\r\n", m_body.size());
-        builder.append((const char*)m_body.data(), m_body.size());
+        builder.append((char const*)m_body.data(), m_body.size());
     }
     builder.append("\r\n");
     return builder.to_byte_buffer();
@@ -169,10 +170,41 @@ Optional<HttpRequest> HttpRequest::from_raw_request(ReadonlyBytes raw_request)
     return request;
 }
 
-void HttpRequest::set_headers(const HashMap<String, String>& headers)
+void HttpRequest::set_headers(HashMap<String, String> const& headers)
 {
     for (auto& it : headers)
         m_headers.append({ it.key, it.value });
 }
 
+Optional<HttpRequest::Header> HttpRequest::get_http_basic_authentication_header(URL const& url)
+{
+    if (!url.includes_credentials())
+        return {};
+    StringBuilder builder;
+    builder.append(url.username());
+    builder.append(':');
+    builder.append(url.password());
+    auto token = encode_base64(builder.to_string().bytes());
+    builder.clear();
+    builder.append("Basic ");
+    builder.append(token);
+    return Header { "Authorization", builder.to_string() };
+}
+
+Optional<HttpRequest::BasicAuthenticationCredentials> HttpRequest::parse_http_basic_authentication_header(String const& value)
+{
+    if (!value.starts_with("Basic ", AK::CaseSensitivity::CaseInsensitive))
+        return {};
+    auto token = value.substring_view(6);
+    if (token.is_empty())
+        return {};
+    auto decoded_token = String::copy(decode_base64(token));
+    auto colon_index = decoded_token.find(':');
+    if (!colon_index.has_value())
+        return {};
+    auto username = decoded_token.substring_view(0, colon_index.value());
+    auto password = decoded_token.substring_view(colon_index.value() + 1);
+    return BasicAuthenticationCredentials { username, password };
+}
+
 }

+ 13 - 6
Userland/Libraries/LibHTTP/HttpRequest.h

@@ -29,28 +29,35 @@ public:
         String value;
     };
 
+    struct BasicAuthenticationCredentials {
+        String username;
+        String password;
+    };
+
     HttpRequest();
     ~HttpRequest();
 
-    const String& resource() const { return m_resource; }
-    const Vector<Header>& headers() const { return m_headers; }
+    String const& resource() const { return m_resource; }
+    Vector<Header> const& headers() const { return m_headers; }
 
-    const URL& url() const { return m_url; }
-    void set_url(const URL& url) { m_url = url; }
+    URL const& url() const { return m_url; }
+    void set_url(URL const& url) { m_url = url; }
 
     Method method() const { return m_method; }
     void set_method(Method method) { m_method = method; }
 
-    const ByteBuffer& body() const { return m_body; }
+    ByteBuffer const& body() const { return m_body; }
     void set_body(ReadonlyBytes body) { m_body = ByteBuffer::copy(body); }
     void set_body(ByteBuffer&& body) { m_body = move(body); }
 
     String method_name() const;
     ByteBuffer to_raw_request() const;
 
-    void set_headers(const HashMap<String, String>&);
+    void set_headers(HashMap<String, String> const&);
 
     static Optional<HttpRequest> from_raw_request(ReadonlyBytes);
+    static Optional<Header> get_http_basic_authentication_header(URL const&);
+    static Optional<BasicAuthenticationCredentials> parse_http_basic_authentication_header(String const&);
 
 private:
     URL m_url;