From e636851481eabdf00953573a5eb459ee52feeacc Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 9 Jun 2024 11:28:37 +0200 Subject: [PATCH] LibHTTP+RequestServer: Add HTTP::HeaderMap and use for response headers Instead of using a HashMap everywhere, we now encapsulate this in a class. Even better, the new class also allows keeping track of multiple headers with the same name! This will make it possible for HTTP responses to actually retain all their headers on the perilous journey from RequestServer to LibWeb. --- Ladybird/Qt/RequestManagerQt.cpp | 2 +- Userland/Libraries/LibCore/NetworkJob.h | 3 +- Userland/Libraries/LibHTTP/Header.h | 40 ++++++++++++ Userland/Libraries/LibHTTP/HeaderMap.h | 65 +++++++++++++++++++ Userland/Libraries/LibHTTP/HttpResponse.cpp | 2 +- Userland/Libraries/LibHTTP/HttpResponse.h | 9 +-- Userland/Libraries/LibHTTP/Job.h | 2 +- Userland/Libraries/LibProtocol/Request.cpp | 2 +- Userland/Libraries/LibProtocol/Request.h | 9 +-- .../Libraries/LibProtocol/RequestClient.cpp | 10 +-- .../Libraries/LibProtocol/RequestClient.h | 3 +- .../LibWeb/Fetch/Fetching/Fetching.cpp | 6 +- .../LibWeb/HTML/HTMLObjectElement.cpp | 12 ++-- Userland/Libraries/LibWeb/Loader/Resource.cpp | 4 +- Userland/Libraries/LibWeb/Loader/Resource.h | 7 +- .../LibWeb/Loader/ResourceLoader.cpp | 12 ++-- .../Libraries/LibWeb/Loader/ResourceLoader.h | 8 +-- .../RequestServer/ConnectionFromClient.cpp | 3 +- Userland/Services/RequestServer/Request.cpp | 4 +- Userland/Services/RequestServer/Request.h | 6 +- .../Services/RequestServer/RequestClient.ipc | 3 +- 21 files changed, 159 insertions(+), 53 deletions(-) create mode 100644 Userland/Libraries/LibHTTP/Header.h create mode 100644 Userland/Libraries/LibHTTP/HeaderMap.h diff --git a/Ladybird/Qt/RequestManagerQt.cpp b/Ladybird/Qt/RequestManagerQt.cpp index cec138b1d28..0c295a2bb24 100644 --- a/Ladybird/Qt/RequestManagerQt.cpp +++ b/Ladybird/Qt/RequestManagerQt.cpp @@ -112,7 +112,7 @@ void RequestManagerQt::Request::did_finish() { auto buffer = m_reply.readAll(); auto http_status_code = m_reply.attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt(); - HashMap response_headers; + HTTP::HeaderMap response_headers; Vector set_cookie_headers; for (auto& it : m_reply.rawHeaderPairs()) { auto name = ByteString(it.first.data(), it.first.length()); diff --git a/Userland/Libraries/LibCore/NetworkJob.h b/Userland/Libraries/LibCore/NetworkJob.h index dad0f5a5390..e8df3e38c9b 100644 --- a/Userland/Libraries/LibCore/NetworkJob.h +++ b/Userland/Libraries/LibCore/NetworkJob.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace Core { @@ -27,7 +28,7 @@ public: virtual ~NetworkJob() override = default; // Could fire twice, after Headers and after Trailers! - Function const& response_headers, Optional response_code)> on_headers_received; + Function response_code)> on_headers_received; Function on_finish; Function, u64)> on_progress; diff --git a/Userland/Libraries/LibHTTP/Header.h b/Userland/Libraries/LibHTTP/Header.h new file mode 100644 index 00000000000..e43c2196b72 --- /dev/null +++ b/Userland/Libraries/LibHTTP/Header.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace HTTP { + +struct Header { + ByteString name; + ByteString value; +}; + +} + +namespace IPC { + +template<> +inline ErrorOr encode(Encoder& encoder, HTTP::Header const& header) +{ + TRY(encoder.encode(header.name)); + TRY(encoder.encode(header.value)); + return {}; +} + +template<> +inline ErrorOr decode(Decoder& decoder) +{ + auto name = TRY(decoder.decode()); + auto value = TRY(decoder.decode()); + return HTTP::Header { move(name), move(value) }; +} + +} diff --git a/Userland/Libraries/LibHTTP/HeaderMap.h b/Userland/Libraries/LibHTTP/HeaderMap.h new file mode 100644 index 00000000000..f9b8554faae --- /dev/null +++ b/Userland/Libraries/LibHTTP/HeaderMap.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace HTTP { + +class HeaderMap { +public: + HeaderMap() = default; + ~HeaderMap() = default; + + void set(ByteString name, ByteString value) + { + m_map.set(name, value); + m_headers.append({ move(name), move(value) }); + } + + [[nodiscard]] bool contains(ByteString const& name) const + { + return m_map.contains(name); + } + + [[nodiscard]] Optional get(ByteString const& name) const + { + return m_map.get(name); + } + + [[nodiscard]] Vector
const& headers() const + { + return m_headers; + } + +private: + HashMap m_map; + Vector
m_headers; +}; + +} + +namespace IPC { + +template<> +inline ErrorOr encode(Encoder& encoder, HTTP::HeaderMap const& header_map) +{ + TRY(encoder.encode(header_map.headers())); + return {}; +} + +template<> +inline ErrorOr decode(Decoder& decoder) +{ + auto headers = TRY(decoder.decode>()); + HTTP::HeaderMap header_map; + for (auto& header : headers) + header_map.set(move(header.name), move(header.value)); + return header_map; +} + +} diff --git a/Userland/Libraries/LibHTTP/HttpResponse.cpp b/Userland/Libraries/LibHTTP/HttpResponse.cpp index f9f7af49756..97bad2d0615 100644 --- a/Userland/Libraries/LibHTTP/HttpResponse.cpp +++ b/Userland/Libraries/LibHTTP/HttpResponse.cpp @@ -9,7 +9,7 @@ namespace HTTP { -HttpResponse::HttpResponse(int code, HashMap&& headers, size_t size) +HttpResponse::HttpResponse(int code, HeaderMap&& headers, size_t size) : m_code(code) , m_headers(move(headers)) , m_downloaded_size(size) diff --git a/Userland/Libraries/LibHTTP/HttpResponse.h b/Userland/Libraries/LibHTTP/HttpResponse.h index 8215f103bf2..9cfd7fbfc92 100644 --- a/Userland/Libraries/LibHTTP/HttpResponse.h +++ b/Userland/Libraries/LibHTTP/HttpResponse.h @@ -10,13 +10,14 @@ #include #include #include +#include namespace HTTP { class HttpResponse : public Core::NetworkResponse { public: virtual ~HttpResponse() override = default; - static NonnullRefPtr create(int code, HashMap&& headers, size_t downloaded_size) + static NonnullRefPtr create(int code, HeaderMap&& headers, size_t downloaded_size) { return adopt_ref(*new HttpResponse(code, move(headers), downloaded_size)); } @@ -24,15 +25,15 @@ public: int code() const { return m_code; } size_t downloaded_size() const { return m_downloaded_size; } StringView reason_phrase() const { return reason_phrase_for_code(m_code); } - HashMap const& headers() const { return m_headers; } + HeaderMap const& headers() const { return m_headers; } static StringView reason_phrase_for_code(int code); private: - HttpResponse(int code, HashMap&&, size_t size); + HttpResponse(int code, HeaderMap&&, size_t size); int m_code { 0 }; - HashMap m_headers; + HeaderMap m_headers; size_t m_downloaded_size { 0 }; }; diff --git a/Userland/Libraries/LibHTTP/Job.h b/Userland/Libraries/LibHTTP/Job.h index 4da1c9be45e..14d91152975 100644 --- a/Userland/Libraries/LibHTTP/Job.h +++ b/Userland/Libraries/LibHTTP/Job.h @@ -53,7 +53,7 @@ protected: Core::BufferedSocketBase* m_socket { nullptr }; bool m_legacy_connection { false }; int m_code { -1 }; - HashMap m_headers; + HTTP::HeaderMap m_headers; Vector m_set_cookie_headers; struct ReceivedBuffer { diff --git a/Userland/Libraries/LibProtocol/Request.cpp b/Userland/Libraries/LibProtocol/Request.cpp index 2218418fa7e..06b6c305cec 100644 --- a/Userland/Libraries/LibProtocol/Request.cpp +++ b/Userland/Libraries/LibProtocol/Request.cpp @@ -94,7 +94,7 @@ void Request::did_progress(Badge, Optional total_size, u64 d on_progress(total_size, downloaded_size); } -void Request::did_receive_headers(Badge, HashMap const& response_headers, Optional response_code) +void Request::did_receive_headers(Badge, HTTP::HeaderMap const& response_headers, Optional response_code) { if (on_headers_received) on_headers_received(response_headers, response_code); diff --git a/Userland/Libraries/LibProtocol/Request.h b/Userland/Libraries/LibProtocol/Request.h index ef7736b9697..7376f880c95 100644 --- a/Userland/Libraries/LibProtocol/Request.h +++ b/Userland/Libraries/LibProtocol/Request.h @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace Protocol { @@ -36,13 +37,13 @@ public: int fd() const { return m_fd; } bool stop(); - using BufferedRequestFinished = Function const& response_headers, Optional response_code, ReadonlyBytes payload)>; + using BufferedRequestFinished = Function response_code, ReadonlyBytes payload)>; // Configure the request such that the entirety of the response data is buffered. The callback receives that data and // the response headers all at once. Using this method is mutually exclusive with `set_unbuffered_data_received_callback`. void set_buffered_request_finished_callback(BufferedRequestFinished); - using HeadersReceived = Function const& response_headers, Optional response_code)>; + using HeadersReceived = Function response_code)>; using DataReceived = Function; using RequestFinished = Function; @@ -55,7 +56,7 @@ public: void did_finish(Badge, bool success, u64 total_size); void did_progress(Badge, Optional total_size, u64 downloaded_size); - void did_receive_headers(Badge, HashMap const& response_headers, Optional response_code); + void did_receive_headers(Badge, HTTP::HeaderMap const& response_headers, Optional response_code); void did_request_certificates(Badge); RefPtr& write_notifier(Badge) { return m_write_notifier; } @@ -83,7 +84,7 @@ private: struct InternalBufferedData { AllocatingMemoryStream payload_stream; - HashMap response_headers; + HTTP::HeaderMap response_headers; Optional response_code; }; diff --git a/Userland/Libraries/LibProtocol/RequestClient.cpp b/Userland/Libraries/LibProtocol/RequestClient.cpp index fd557581f2e..82b88cd0b05 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.cpp +++ b/Userland/Libraries/LibProtocol/RequestClient.cpp @@ -87,20 +87,14 @@ void RequestClient::request_progress(i32 request_id, Optional const& total_ } } -void RequestClient::headers_became_available(i32 request_id, HashMap const& response_headers, Optional const& status_code) +void RequestClient::headers_became_available(i32 request_id, HTTP::HeaderMap const& response_headers, Optional const& status_code) { auto request = const_cast(m_requests.get(request_id).value_or(nullptr)); if (!request) { warnln("Received headers for non-existent request {}", request_id); return; } - auto response_headers_clone_or_error = response_headers.clone(); - if (response_headers_clone_or_error.is_error()) { - warnln("Error while receiving headers for request {}: {}", request_id, response_headers_clone_or_error.error()); - return; - } - - request->did_receive_headers({}, response_headers_clone_or_error.release_value(), status_code); + request->did_receive_headers({}, response_headers, status_code); } void RequestClient::certificate_requested(i32 request_id) diff --git a/Userland/Libraries/LibProtocol/RequestClient.h b/Userland/Libraries/LibProtocol/RequestClient.h index bbf447353e5..32b0337e625 100644 --- a/Userland/Libraries/LibProtocol/RequestClient.h +++ b/Userland/Libraries/LibProtocol/RequestClient.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -42,7 +43,7 @@ private: virtual void request_progress(i32, Optional const&, u64) override; virtual void request_finished(i32, bool, u64) override; virtual void certificate_requested(i32) override; - virtual void headers_became_available(i32, HashMap const&, Optional const&) override; + virtual void headers_became_available(i32, HTTP::HeaderMap const&, Optional const&) override; virtual void websocket_connected(i32) override; virtual void websocket_received(i32, bool, ByteBuffer const&) override; diff --git a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index f85c0d86f1f..db0a71634c6 100644 --- a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -1985,7 +1985,7 @@ WebIDL::ExceptionOr> nonstandard_resource_load log_response(status_code, response_headers, ReadonlyBytes {}); } - for (auto const& [name, value] : response_headers) { + for (auto const& [name, value] : response_headers.headers()) { auto header = Infrastructure::Header::from_string_pair(name, value); response->header_list()->append(move(header)); } @@ -2050,7 +2050,7 @@ WebIDL::ExceptionOr> nonstandard_resource_load auto response = Infrastructure::Response::create(vm); response->set_status(status_code.value_or(200)); response->set_body(move(body)); - for (auto const& [name, value] : response_headers) { + for (auto const& [name, value] : response_headers.headers()) { auto header = Infrastructure::Header::from_string_pair(name, value); response->header_list()->append(move(header)); } @@ -2071,7 +2071,7 @@ WebIDL::ExceptionOr> nonstandard_resource_load response->set_status(status_code.value_or(400)); auto [body, _] = TRY_OR_IGNORE(extract_body(realm, data)); response->set_body(move(body)); - for (auto const& [name, value] : response_headers) { + for (auto const& [name, value] : response_headers.headers()) { auto header = Infrastructure::Header::from_string_pair(name, value); response->header_list()->append(move(header)); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index 16056620c07..cfc054fbbe9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -183,13 +183,15 @@ void HTMLObjectElement::resource_did_load() // 4. Run the appropriate set of steps from the following list: // * If the resource has associated Content-Type metadata - if (auto it = resource()->response_headers().find("Content-Type"sv); it != resource()->response_headers().end()) { + if (auto maybe_content_type = resource()->response_headers().get("Content-Type"sv); maybe_content_type.has_value()) { + auto& content_type = maybe_content_type.value(); + // 1. Let binary be false. bool binary = false; // 2. If the type specified in the resource's Content-Type metadata is "text/plain", and the result of applying the rules for distinguishing if a resource is text or binary to the resource is that the resource is not text/plain, then set binary to true. - if (it->value == "text/plain"sv) { - auto supplied_type = MimeSniff::MimeType::parse(it->value).release_value_but_fixme_should_propagate_errors(); + if (content_type == "text/plain"sv) { + auto supplied_type = MimeSniff::MimeType::parse(content_type).release_value_but_fixme_should_propagate_errors(); auto computed_type = MimeSniff::Resource::sniff(resource()->encoded_data(), MimeSniff::SniffingConfiguration { .sniffing_context = MimeSniff::SniffingContext::TextOrBinary, .supplied_type = move(supplied_type), @@ -200,12 +202,12 @@ void HTMLObjectElement::resource_did_load() } // 3. If the type specified in the resource's Content-Type metadata is "application/octet-stream", then set binary to true. - if (it->value == "application/octet-stream"sv) + if (content_type == "application/octet-stream"sv) binary = true; // 4. If binary is false, then let the resource type be the type specified in the resource's Content-Type metadata, and jump to the step below labeled handler. if (!binary) - return run_object_representation_handler_steps(it->value); + return run_object_representation_handler_steps(content_type); // 5. If there is a type attribute present on the object element, and its value is not application/octet-stream, then run the following steps: if (auto type = this->type(); !type.is_empty() && (type != "application/octet-stream"sv)) { diff --git a/Userland/Libraries/LibWeb/Loader/Resource.cpp b/Userland/Libraries/LibWeb/Loader/Resource.cpp index c4037cbdfe5..817cd12406e 100644 --- a/Userland/Libraries/LibWeb/Loader/Resource.cpp +++ b/Userland/Libraries/LibWeb/Loader/Resource.cpp @@ -83,12 +83,12 @@ static bool is_valid_encoding(StringView encoding) return TextCodec::decoder_for(encoding).has_value(); } -void Resource::did_load(Badge, ReadonlyBytes data, HashMap const& headers, Optional status_code) +void Resource::did_load(Badge, ReadonlyBytes data, HTTP::HeaderMap const& headers, Optional status_code) { VERIFY(m_state == State::Pending); // FIXME: Handle OOM failure. m_encoded_data = ByteBuffer::copy(data).release_value_but_fixme_should_propagate_errors(); - m_response_headers = headers.clone().release_value_but_fixme_should_propagate_errors(); + m_response_headers = headers; m_status_code = move(status_code); m_state = State::Loaded; diff --git a/Userland/Libraries/LibWeb/Loader/Resource.h b/Userland/Libraries/LibWeb/Loader/Resource.h index 1a27f5b5945..3201271cc92 100644 --- a/Userland/Libraries/LibWeb/Loader/Resource.h +++ b/Userland/Libraries/LibWeb/Loader/Resource.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ public: const URL::URL& url() const { return m_request.url(); } ByteBuffer const& encoded_data() const { return m_encoded_data; } - HashMap const& response_headers() const { return m_response_headers; } + [[nodiscard]] HTTP::HeaderMap const& response_headers() const { return m_response_headers; } [[nodiscard]] Optional status_code() const { return m_status_code; } @@ -66,7 +67,7 @@ public: void for_each_client(Function); - void did_load(Badge, ReadonlyBytes data, HashMap const& headers, Optional status_code); + void did_load(Badge, ReadonlyBytes data, HTTP::HeaderMap const&, Optional status_code); void did_fail(Badge, ByteString const& error, Optional status_code); protected: @@ -84,7 +85,7 @@ private: Optional m_encoding; ByteString m_mime_type; - HashMap m_response_headers; + HTTP::HeaderMap m_response_headers; Optional m_status_code; HashTable m_clients; }; diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp index 9658502c404..548a8113371 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp @@ -166,13 +166,13 @@ static void store_response_cookies(Page& page, URL::URL const& url, ByteString c } } -static HashMap response_headers_for_file(StringView path, Optional const& modified_time) +static HTTP::HeaderMap response_headers_for_file(StringView path, Optional const& modified_time) { // For file:// and resource:// URLs, we have to guess the MIME type, since there's no HTTP header to tell us what // it is. We insert a fake Content-Type header here, so that clients can use it to learn the MIME type. auto mime_type = Core::guess_mime_type_based_on_filename(path); - HashMap response_headers; + HTTP::HeaderMap response_headers; response_headers.set("Content-Type"sv, mime_type); if (modified_time.has_value()) { @@ -258,7 +258,7 @@ void ResourceLoader::load(LoadRequest& request, SuccessCallback success_callback } log_success(request); - HashMap response_headers; + HTTP::HeaderMap response_headers; response_headers.set("Content-Type"sv, "text/html"sv); success_callback(maybe_response.release_value().bytes(), response_headers, {}); }; @@ -267,7 +267,7 @@ void ResourceLoader::load(LoadRequest& request, SuccessCallback success_callback dbgln_if(SPAM_DEBUG, "Loading about: URL {}", url); log_success(request); - HashMap response_headers; + HTTP::HeaderMap response_headers; response_headers.set("Content-Type", "text/html; charset=UTF-8"); // About version page @@ -304,7 +304,7 @@ void ResourceLoader::load(LoadRequest& request, SuccessCallback success_callback MUST(data_url.mime_type.serialized()), StringView(data_url.body.bytes())); - HashMap response_headers; + HTTP::HeaderMap response_headers; response_headers.set("Content-Type", MUST(data_url.mime_type.serialized()).to_byte_string()); log_success(request); @@ -537,7 +537,7 @@ RefPtr ResourceLoader::start_network_request(Loa return protocol_request; } -void ResourceLoader::handle_network_response_headers(LoadRequest const& request, HashMap const& response_headers) +void ResourceLoader::handle_network_response_headers(LoadRequest const& request, HTTP::HeaderMap const& response_headers) { if (!request.page()) return; diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h index f8423427537..434daceaae1 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h @@ -72,13 +72,13 @@ public: RefPtr load_resource(Resource::Type, LoadRequest&); - using SuccessCallback = JS::SafeFunction const& response_headers, Optional status_code)>; - using ErrorCallback = JS::SafeFunction status_code, ReadonlyBytes payload, HashMap const& response_headers)>; + using SuccessCallback = JS::SafeFunction status_code)>; + using ErrorCallback = JS::SafeFunction status_code, ReadonlyBytes payload, HTTP::HeaderMap const& response_headers)>; using TimeoutCallback = JS::SafeFunction; void load(LoadRequest&, SuccessCallback success_callback, ErrorCallback error_callback = nullptr, Optional timeout = {}, TimeoutCallback timeout_callback = nullptr); - using OnHeadersReceived = JS::SafeFunction const& response_headers, Optional status_code)>; + using OnHeadersReceived = JS::SafeFunction status_code)>; using OnDataReceived = JS::SafeFunction; using OnComplete = JS::SafeFunction error_message)>; @@ -107,7 +107,7 @@ private: static ErrorOr> try_create(NonnullRefPtr); RefPtr start_network_request(LoadRequest const&); - void handle_network_response_headers(LoadRequest const&, HashMap const&); + void handle_network_response_headers(LoadRequest const&, HTTP::HeaderMap const&); void finish_network_request(NonnullRefPtr const&); int m_pending_loads { 0 }; diff --git a/Userland/Services/RequestServer/ConnectionFromClient.cpp b/Userland/Services/RequestServer/ConnectionFromClient.cpp index 8fadfd49a39..f561dc912a1 100644 --- a/Userland/Services/RequestServer/ConnectionFromClient.cpp +++ b/Userland/Services/RequestServer/ConnectionFromClient.cpp @@ -231,9 +231,8 @@ Messages::RequestServer::StopRequestResponse ConnectionFromClient::stop_request( void ConnectionFromClient::did_receive_headers(Badge, Request& request) { - auto response_headers = request.response_headers().clone().release_value_but_fixme_should_propagate_errors(); auto lock = Threading::MutexLocker(m_ipc_mutex); - async_headers_became_available(request.id(), move(response_headers), request.status_code()); + async_headers_became_available(request.id(), request.response_headers(), request.status_code()); } void ConnectionFromClient::did_finish_request(Badge, Request& request, bool success) diff --git a/Userland/Services/RequestServer/Request.cpp b/Userland/Services/RequestServer/Request.cpp index f9663a0c777..09babd59059 100644 --- a/Userland/Services/RequestServer/Request.cpp +++ b/Userland/Services/RequestServer/Request.cpp @@ -21,9 +21,9 @@ void Request::stop() m_client.did_finish_request({}, *this, false); } -void Request::set_response_headers(HashMap const& response_headers) +void Request::set_response_headers(HTTP::HeaderMap response_headers) { - m_response_headers = response_headers; + m_response_headers = move(response_headers); m_client.did_receive_headers({}, *this); } diff --git a/Userland/Services/RequestServer/Request.h b/Userland/Services/RequestServer/Request.h index 4d0001a7657..31ec9023f67 100644 --- a/Userland/Services/RequestServer/Request.h +++ b/Userland/Services/RequestServer/Request.h @@ -25,7 +25,7 @@ public: Optional status_code() const { return m_status_code; } Optional total_size() const { return m_total_size; } size_t downloaded_size() const { return m_downloaded_size; } - HashMap const& response_headers() const { return m_response_headers; } + HTTP::HeaderMap const& response_headers() const { return m_response_headers; } void stop(); virtual void set_certificate(ByteString, ByteString); @@ -38,7 +38,7 @@ public: void did_progress(Optional total_size, u64 downloaded_size); void set_status_code(u32 status_code) { m_status_code = status_code; } void did_request_certificates(); - void set_response_headers(HashMap const&); + void set_response_headers(HTTP::HeaderMap); void set_downloaded_size(size_t size) { m_downloaded_size = size; } Core::File const& output_stream() const { return *m_output_stream; } @@ -53,7 +53,7 @@ private: Optional m_total_size {}; size_t m_downloaded_size { 0 }; NonnullOwnPtr m_output_stream; - HashMap m_response_headers; + HTTP::HeaderMap m_response_headers; }; } diff --git a/Userland/Services/RequestServer/RequestClient.ipc b/Userland/Services/RequestServer/RequestClient.ipc index 2a9b0128bc5..46cb89cdbdb 100644 --- a/Userland/Services/RequestServer/RequestClient.ipc +++ b/Userland/Services/RequestServer/RequestClient.ipc @@ -1,3 +1,4 @@ +#include #include endpoint RequestClient @@ -5,7 +6,7 @@ endpoint RequestClient request_started(i32 request_id, IPC::File fd) =| request_progress(i32 request_id, Optional total_size, u64 downloaded_size) =| request_finished(i32 request_id, bool success, u64 total_size) =| - headers_became_available(i32 request_id, HashMap response_headers, Optional status_code) =| + headers_became_available(i32 request_id, HTTP::HeaderMap response_headers, Optional status_code) =| // Websocket API // FIXME: See if this can be merged with the regular APIs