From 897998017af64a641ddbd82e5d12d08f6bcc2aea Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 21 May 2020 12:27:42 +0200 Subject: [PATCH] ProtocolServer: Support request headers You can now pass a dictionary of request headers when starting a new download in ProtocolServer. The HTTP and HTTPS protocol will include the headers in their requests. --- Libraries/LibHTTP/HttpRequest.cpp | 15 ++++++++++++++- Libraries/LibHTTP/HttpRequest.h | 2 ++ Libraries/LibProtocol/Client.cpp | 8 ++++++-- Libraries/LibProtocol/Client.h | 3 ++- Services/ProtocolServer/ClientConnection.cpp | 2 +- Services/ProtocolServer/GeminiProtocol.cpp | 2 +- Services/ProtocolServer/GeminiProtocol.h | 2 +- Services/ProtocolServer/HttpProtocol.cpp | 3 ++- Services/ProtocolServer/HttpProtocol.h | 2 +- Services/ProtocolServer/HttpsProtocol.cpp | 3 ++- Services/ProtocolServer/HttpsProtocol.h | 2 +- Services/ProtocolServer/Protocol.h | 2 +- Services/ProtocolServer/ProtocolServer.ipc | 2 +- 13 files changed, 35 insertions(+), 13 deletions(-) diff --git a/Libraries/LibHTTP/HttpRequest.cpp b/Libraries/LibHTTP/HttpRequest.cpp index f3ba313cae..075fe55197 100644 --- a/Libraries/LibHTTP/HttpRequest.cpp +++ b/Libraries/LibHTTP/HttpRequest.cpp @@ -71,7 +71,14 @@ ByteBuffer HttpRequest::to_raw_request() const } builder.append(" HTTP/1.1\r\nHost: "); builder.append(m_url.host()); - builder.append("\r\nConnection: close\r\n\r\n"); + builder.append("\r\n"); + for (auto& header : m_headers) { + builder.append(header.name); + builder.append(": "); + builder.append(header.value); + builder.append("\r\n"); + } + builder.append("Connection: close\r\n\r\n"); return builder.to_byte_buffer(); } @@ -181,4 +188,10 @@ Optional HttpRequest::from_raw_request(const ByteBuffer& raw_reques return request; } +void HttpRequest::set_headers(const HashMap& headers) +{ + for (auto& it : headers) + m_headers.append({ it.key, it.value }); +} + } diff --git a/Libraries/LibHTTP/HttpRequest.h b/Libraries/LibHTTP/HttpRequest.h index 44f30b5c01..f7e0a0783e 100644 --- a/Libraries/LibHTTP/HttpRequest.h +++ b/Libraries/LibHTTP/HttpRequest.h @@ -65,6 +65,8 @@ public: RefPtr schedule(); + void set_headers(const HashMap&); + static Optional from_raw_request(const ByteBuffer&); private: diff --git a/Libraries/LibProtocol/Client.cpp b/Libraries/LibProtocol/Client.cpp index e13cbb2db7..303910dce2 100644 --- a/Libraries/LibProtocol/Client.cpp +++ b/Libraries/LibProtocol/Client.cpp @@ -47,9 +47,13 @@ bool Client::is_supported_protocol(const String& protocol) return send_sync(protocol)->supported(); } -RefPtr Client::start_download(const String& url) +RefPtr Client::start_download(const String& url, const HashMap& request_headers) { - i32 download_id = send_sync(url)->download_id(); + IPC::Dictionary header_dictionary; + for (auto& it : request_headers) + header_dictionary.add(it.key, it.value); + + i32 download_id = send_sync(url, header_dictionary)->download_id(); if (download_id < 0) return nullptr; auto download = Download::create_from_id({}, *this, download_id); diff --git a/Libraries/LibProtocol/Client.h b/Libraries/LibProtocol/Client.h index e8014cb289..37351710fa 100644 --- a/Libraries/LibProtocol/Client.h +++ b/Libraries/LibProtocol/Client.h @@ -44,7 +44,8 @@ public: virtual void handshake() override; bool is_supported_protocol(const String&); - RefPtr start_download(const String& url); + RefPtr start_download(const String& url, const HashMap& request_headers = {}); + bool stop_download(Badge, Download&); diff --git a/Services/ProtocolServer/ClientConnection.cpp b/Services/ProtocolServer/ClientConnection.cpp index 40387f4208..f688dc58a8 100644 --- a/Services/ProtocolServer/ClientConnection.cpp +++ b/Services/ProtocolServer/ClientConnection.cpp @@ -64,7 +64,7 @@ OwnPtr ClientConnection::handle auto* protocol = Protocol::find_by_name(url.protocol()); if (!protocol) return make(-1); - auto download = protocol->start_download(*this, url); + auto download = protocol->start_download(*this, url, message.request_headers().entries()); if (!download) return make(-1); auto id = download->id(); diff --git a/Services/ProtocolServer/GeminiProtocol.cpp b/Services/ProtocolServer/GeminiProtocol.cpp index 956633b177..9bc61d54aa 100644 --- a/Services/ProtocolServer/GeminiProtocol.cpp +++ b/Services/ProtocolServer/GeminiProtocol.cpp @@ -40,7 +40,7 @@ GeminiProtocol::~GeminiProtocol() { } -OwnPtr GeminiProtocol::start_download(ClientConnection& client, const URL& url) +OwnPtr GeminiProtocol::start_download(ClientConnection& client, const URL& url, const HashMap&) { Gemini::GeminiRequest request; request.set_url(url); diff --git a/Services/ProtocolServer/GeminiProtocol.h b/Services/ProtocolServer/GeminiProtocol.h index e72f4e324f..e3f28bf57d 100644 --- a/Services/ProtocolServer/GeminiProtocol.h +++ b/Services/ProtocolServer/GeminiProtocol.h @@ -35,7 +35,7 @@ public: GeminiProtocol(); virtual ~GeminiProtocol() override; - virtual OwnPtr start_download(ClientConnection&, const URL&) override; + virtual OwnPtr start_download(ClientConnection&, const URL&, const HashMap&) override; }; } diff --git a/Services/ProtocolServer/HttpProtocol.cpp b/Services/ProtocolServer/HttpProtocol.cpp index ecd03eaa80..7eaa51287c 100644 --- a/Services/ProtocolServer/HttpProtocol.cpp +++ b/Services/ProtocolServer/HttpProtocol.cpp @@ -40,11 +40,12 @@ HttpProtocol::~HttpProtocol() { } -OwnPtr HttpProtocol::start_download(ClientConnection& client, const URL& url) +OwnPtr HttpProtocol::start_download(ClientConnection& client, const URL& url, const HashMap& headers) { HTTP::HttpRequest request; request.set_method(HTTP::HttpRequest::Method::GET); request.set_url(url); + request.set_headers(headers); auto job = request.schedule(); if (!job) return nullptr; diff --git a/Services/ProtocolServer/HttpProtocol.h b/Services/ProtocolServer/HttpProtocol.h index b382a255d4..ee0c0f5f3b 100644 --- a/Services/ProtocolServer/HttpProtocol.h +++ b/Services/ProtocolServer/HttpProtocol.h @@ -35,7 +35,7 @@ public: HttpProtocol(); virtual ~HttpProtocol() override; - virtual OwnPtr start_download(ClientConnection&, const URL&) override; + virtual OwnPtr start_download(ClientConnection&, const URL&, const HashMap& headers) override; }; } diff --git a/Services/ProtocolServer/HttpsProtocol.cpp b/Services/ProtocolServer/HttpsProtocol.cpp index f1e964e78f..ab1181cb69 100644 --- a/Services/ProtocolServer/HttpsProtocol.cpp +++ b/Services/ProtocolServer/HttpsProtocol.cpp @@ -40,11 +40,12 @@ HttpsProtocol::~HttpsProtocol() { } -OwnPtr HttpsProtocol::start_download(ClientConnection& client, const URL& url) +OwnPtr HttpsProtocol::start_download(ClientConnection& client, const URL& url, const HashMap& headers) { HTTP::HttpRequest request; request.set_method(HTTP::HttpRequest::Method::GET); request.set_url(url); + request.set_headers(headers); auto job = HTTP::HttpsJob::construct(request); auto download = HttpsDownload::create_with_job({}, client, (HTTP::HttpsJob&)*job); job->start(); diff --git a/Services/ProtocolServer/HttpsProtocol.h b/Services/ProtocolServer/HttpsProtocol.h index ab6dae90dd..92f72e8729 100644 --- a/Services/ProtocolServer/HttpsProtocol.h +++ b/Services/ProtocolServer/HttpsProtocol.h @@ -35,7 +35,7 @@ public: HttpsProtocol(); virtual ~HttpsProtocol() override; - virtual OwnPtr start_download(ClientConnection&, const URL&) override; + virtual OwnPtr start_download(ClientConnection&, const URL&, const HashMap& headers) override; }; } diff --git a/Services/ProtocolServer/Protocol.h b/Services/ProtocolServer/Protocol.h index b50e97195d..13cff2e7bb 100644 --- a/Services/ProtocolServer/Protocol.h +++ b/Services/ProtocolServer/Protocol.h @@ -37,7 +37,7 @@ public: virtual ~Protocol(); const String& name() const { return m_name; } - virtual OwnPtr start_download(ClientConnection&, const URL&) = 0; + virtual OwnPtr start_download(ClientConnection&, const URL&, const HashMap& headers) = 0; static Protocol* find_by_name(const String&); diff --git a/Services/ProtocolServer/ProtocolServer.ipc b/Services/ProtocolServer/ProtocolServer.ipc index 74ec138ab5..c25fc54ca9 100644 --- a/Services/ProtocolServer/ProtocolServer.ipc +++ b/Services/ProtocolServer/ProtocolServer.ipc @@ -10,6 +10,6 @@ endpoint ProtocolServer = 9 IsSupportedProtocol(String protocol) => (bool supported) // Download API - StartDownload(String url) => (i32 download_id) + StartDownload(String url, IPC::Dictionary request_headers) => (i32 download_id) StopDownload(i32 download_id) => (bool success) }