diff --git a/Userland/Libraries/LibRequests/Request.cpp b/Userland/Libraries/LibRequests/Request.cpp index ce916de4cbe..1c711472d7e 100644 --- a/Userland/Libraries/LibRequests/Request.cpp +++ b/Userland/Libraries/LibRequests/Request.cpp @@ -47,9 +47,10 @@ void Request::set_buffered_request_finished_callback(BufferedRequestFinished on_ m_internal_buffered_data = make(); - on_headers_received = [this](auto& headers, auto response_code) { + on_headers_received = [this](auto& headers, auto response_code, auto const& reason_phrase) { m_internal_buffered_data->response_headers = headers; m_internal_buffered_data->response_code = move(response_code); + m_internal_buffered_data->reason_phrase = reason_phrase; }; on_finish = [this, on_buffered_request_finished = move(on_buffered_request_finished)](auto total_size, auto network_error) { @@ -61,6 +62,7 @@ void Request::set_buffered_request_finished_callback(BufferedRequestFinished on_ network_error, m_internal_buffered_data->response_headers, m_internal_buffered_data->response_code, + m_internal_buffered_data->reason_phrase, output_buffer); }; @@ -87,10 +89,10 @@ void Request::did_finish(Badge, u64 total_size, Optional, HTTP::HeaderMap const& response_headers, Optional response_code) +void Request::did_receive_headers(Badge, HTTP::HeaderMap const& response_headers, Optional response_code, Optional const& reason_phrase) { if (on_headers_received) - on_headers_received(response_headers, response_code); + on_headers_received(response_headers, response_code, reason_phrase); } void Request::did_request_certificates(Badge) diff --git a/Userland/Libraries/LibRequests/Request.h b/Userland/Libraries/LibRequests/Request.h index bef9cd08969..da52fed8ca6 100644 --- a/Userland/Libraries/LibRequests/Request.h +++ b/Userland/Libraries/LibRequests/Request.h @@ -38,13 +38,13 @@ public: int fd() const { return m_fd; } bool stop(); - using BufferedRequestFinished = Function const& network_error, HTTP::HeaderMap const& response_headers, Optional response_code, ReadonlyBytes payload)>; + using BufferedRequestFinished = Function const& network_error, HTTP::HeaderMap const& response_headers, Optional response_code, Optional reason_phrase, 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 response_code)>; + using HeadersReceived = Function response_code, Optional const& reason_phrase)>; using DataReceived = Function; using RequestFinished = Function network_error)>; @@ -55,7 +55,7 @@ public: Function on_certificate_requested; void did_finish(Badge, u64 total_size, Optional const& network_error); - void did_receive_headers(Badge, HTTP::HeaderMap const& response_headers, Optional response_code); + void did_receive_headers(Badge, HTTP::HeaderMap const& response_headers, Optional response_code, Optional const& reason_phrase); void did_request_certificates(Badge); RefPtr& write_notifier(Badge) { return m_write_notifier; } @@ -85,6 +85,7 @@ private: AllocatingMemoryStream payload_stream; HTTP::HeaderMap response_headers; Optional response_code; + Optional reason_phrase; }; struct InternalStreamData { diff --git a/Userland/Libraries/LibRequests/RequestClient.cpp b/Userland/Libraries/LibRequests/RequestClient.cpp index 67805af5d3b..7df8af35d31 100644 --- a/Userland/Libraries/LibRequests/RequestClient.cpp +++ b/Userland/Libraries/LibRequests/RequestClient.cpp @@ -77,14 +77,14 @@ void RequestClient::request_finished(i32 request_id, u64 total_size, Optional const& status_code) +void RequestClient::headers_became_available(i32 request_id, HTTP::HeaderMap const& response_headers, Optional const& status_code, Optional const& reason_phrase) { auto request = const_cast(m_requests.get(request_id).value_or(nullptr)); if (!request) { warnln("Received headers for non-existent request {}", request_id); return; } - request->did_receive_headers({}, response_headers, status_code); + request->did_receive_headers({}, response_headers, status_code, reason_phrase); } void RequestClient::certificate_requested(i32 request_id) diff --git a/Userland/Libraries/LibRequests/RequestClient.h b/Userland/Libraries/LibRequests/RequestClient.h index ba85737da99..0592c97d450 100644 --- a/Userland/Libraries/LibRequests/RequestClient.h +++ b/Userland/Libraries/LibRequests/RequestClient.h @@ -42,7 +42,7 @@ private: virtual void request_started(i32, IPC::File const&) override; virtual void request_finished(i32, u64, Optional const&) override; virtual void certificate_requested(i32) override; - virtual void headers_became_available(i32, HTTP::HeaderMap const&, Optional const&) override; + virtual void headers_became_available(i32, HTTP::HeaderMap const&, Optional const&, Optional const&) override; virtual void websocket_connected(i64 websocket_id) override; virtual void websocket_received(i64 websocket_id, bool, ByteBuffer const&) override; diff --git a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index fa569d02e90..ae4fc188418 100644 --- a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -2260,7 +2260,7 @@ WebIDL::ExceptionOr> nonstandard_resource_load // 13. Set up stream with byte reading support with pullAlgorithm set to pullAlgorithm, cancelAlgorithm set to cancelAlgorithm. Streams::set_up_readable_stream_controller_with_byte_reading_support(stream, pull_algorithm, cancel_algorithm); - auto on_headers_received = JS::create_heap_function(vm.heap(), [&vm, request, pending_response, stream](HTTP::HeaderMap const& response_headers, Optional status_code) { + auto on_headers_received = JS::create_heap_function(vm.heap(), [&vm, request, pending_response, stream](HTTP::HeaderMap const& response_headers, Optional status_code, Optional const& reason_phrase) { (void)request; if (pending_response->is_resolved()) { // RequestServer will send us the response headers twice, the second time being for HTTP trailers. This @@ -2270,7 +2270,9 @@ WebIDL::ExceptionOr> nonstandard_resource_load auto response = Infrastructure::Response::create(vm); response->set_status(status_code.value_or(200)); - // FIXME: Set response status message + + if (reason_phrase.has_value()) + response->set_status_message(MUST(ByteBuffer::copy(reason_phrase.value().bytes()))); if constexpr (WEB_FETCH_DEBUG) { dbgln("Fetch: ResourceLoader load for '{}' {}: (status {})", @@ -2337,7 +2339,7 @@ WebIDL::ExceptionOr> nonstandard_resource_load ResourceLoader::the().load_unbuffered(load_request, on_headers_received, on_data_received, on_complete); } else { - auto on_load_success = JS::create_heap_function(vm.heap(), [&realm, &vm, request, pending_response](ReadonlyBytes data, HTTP::HeaderMap const& response_headers, Optional status_code) { + auto on_load_success = JS::create_heap_function(vm.heap(), [&realm, &vm, request, pending_response](ReadonlyBytes data, HTTP::HeaderMap const& response_headers, Optional status_code, Optional const& reason_phrase) { (void)request; dbgln_if(WEB_FETCH_DEBUG, "Fetch: ResourceLoader load for '{}' complete", request->url()); if constexpr (WEB_FETCH_DEBUG) @@ -2350,11 +2352,14 @@ WebIDL::ExceptionOr> nonstandard_resource_load auto header = Infrastructure::Header::from_string_pair(name, value); response->header_list()->append(move(header)); } - // FIXME: Set response status message + + if (reason_phrase.has_value()) + response->set_status_message(MUST(ByteBuffer::copy(reason_phrase.value().bytes()))); + pending_response->resolve(response); }); - auto on_load_error = JS::create_heap_function(vm.heap(), [&realm, &vm, request, pending_response](ByteString const& error, Optional status_code, ReadonlyBytes data, HTTP::HeaderMap const& response_headers) { + auto on_load_error = JS::create_heap_function(vm.heap(), [&realm, &vm, request, pending_response](ByteString const& error, Optional status_code, Optional const& reason_phrase, ReadonlyBytes data, HTTP::HeaderMap const& response_headers) { (void)request; dbgln_if(WEB_FETCH_DEBUG, "Fetch: ResourceLoader load for '{}' failed: {} (status {})", request->url(), error, status_code.value_or(0)); if constexpr (WEB_FETCH_DEBUG) @@ -2372,7 +2377,9 @@ WebIDL::ExceptionOr> nonstandard_resource_load auto header = Infrastructure::Header::from_string_pair(name, value); response->header_list()->append(move(header)); } - // FIXME: Set response status message + + if (reason_phrase.has_value()) + response->set_status_message(MUST(ByteBuffer::copy(reason_phrase.value().bytes()))); } pending_response->resolve(response); }); diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp index 1a2871f6d71..bdbfb9a3301 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.cpp @@ -108,10 +108,10 @@ RefPtr ResourceLoader::load_resource(Resource::Type type, LoadRequest& load( request, - JS::create_heap_function(m_heap, [=](ReadonlyBytes data, HTTP::HeaderMap const& headers, Optional status_code) { + JS::create_heap_function(m_heap, [=](ReadonlyBytes data, HTTP::HeaderMap const& headers, Optional status_code, Optional const&) { const_cast(*resource).did_load({}, data, headers, status_code); }), - JS::create_heap_function(m_heap, [=](ByteString const& error, Optional status_code, ReadonlyBytes data, HTTP::HeaderMap const& headers) { + JS::create_heap_function(m_heap, [=](ByteString const& error, Optional status_code, Optional const&, ReadonlyBytes data, HTTP::HeaderMap const& headers) { const_cast(*resource).did_fail({}, error, data, headers, status_code); })); @@ -238,7 +238,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ request.start_timer(); if (should_block_request(request)) { - error_callback->function()("Request was blocked", {}, {}, {}); + error_callback->function()("Request was blocked", {}, {}, {}, {}); return; } @@ -247,14 +247,14 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (maybe_response.is_error()) { log_failure(request, maybe_response.error()); if (error_callback) - error_callback->function()(ByteString::formatted("{}", maybe_response.error()), 500u, {}, {}); + error_callback->function()(ByteString::formatted("{}", maybe_response.error()), 500u, {}, {}, {}); return; } log_success(request); HTTP::HeaderMap response_headers; response_headers.set("Content-Type"sv, "text/html"sv); - success_callback->function()(maybe_response.release_value().bytes(), response_headers, {}); + success_callback->function()(maybe_response.release_value().bytes(), response_headers, {}, {}); }; if (url.scheme() == "about") { @@ -266,7 +266,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ // About version page if (url.path_segment_at_index(0) == "version") { - success_callback->function()(MUST(load_about_version_page()).bytes(), response_headers, {}); + success_callback->function()(MUST(load_about_version_page()).bytes(), response_headers, {}, {}); return; } @@ -274,12 +274,12 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ auto resource = Core::Resource::load_from_uri(MUST(String::formatted("resource://ladybird/{}.html", url.path_segment_at_index(0)))); if (!resource.is_error()) { auto data = resource.value()->data(); - success_callback->function()(data, response_headers, {}); + success_callback->function()(data, response_headers, {}, {}); return; } Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(m_heap, [success_callback, response_headers = move(response_headers)] { - success_callback->function()(ByteString::empty().to_byte_buffer(), response_headers, {}); + success_callback->function()(ByteString::empty().to_byte_buffer(), response_headers, {}, {}); })); return; } @@ -289,7 +289,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (data_url_or_error.is_error()) { auto error_message = data_url_or_error.error().string_literal(); log_failure(request, error_message); - error_callback->function()(error_message, {}, {}, {}); + error_callback->function()(error_message, {}, {}, {}, {}); return; } auto data_url = data_url_or_error.release_value(); @@ -304,7 +304,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ log_success(request); Platform::EventLoopPlugin::the().deferred_invoke(JS::create_heap_function(m_heap, [data = move(data_url.body), response_headers = move(response_headers), success_callback] { - success_callback->function()(data, response_headers, {}); + success_callback->function()(data, response_headers, {}, {}); })); return; } @@ -314,7 +314,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (resource.is_error()) { log_failure(request, resource.error()); if (error_callback) - error_callback->function()(ByteString::formatted("{}", resource.error()), {}, {}, {}); + error_callback->function()(ByteString::formatted("{}", resource.error()), {}, {}, {}, {}); return; } @@ -328,7 +328,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ auto response_headers = response_headers_for_file(URL::percent_decode(url.serialize_path()), resource.value()->modified_time()); log_success(request); - success_callback->function()(data, response_headers, {}); + success_callback->function()(data, response_headers, {}, {}); return; } @@ -350,7 +350,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (file_or_error.is_error()) { log_failure(request, file_or_error.error()); if (error_callback) - error_callback->function()(ByteString::formatted("{}", file_or_error.error()), {}, {}, {}); + error_callback->function()(ByteString::formatted("{}", file_or_error.error()), {}, {}, {}, {}); return; } @@ -367,7 +367,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (st_or_error.is_error()) { log_failure(request, st_or_error.error()); if (error_callback) - error_callback->function()(ByteString::formatted("{}", st_or_error.error()), {}, {}, {}); + error_callback->function()(ByteString::formatted("{}", st_or_error.error()), {}, {}, {}, {}); return; } @@ -376,7 +376,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (maybe_file.is_error()) { log_failure(request, maybe_file.error()); if (error_callback) - error_callback->function()(ByteString::formatted("{}", maybe_file.error()), {}, {}, {}); + error_callback->function()(ByteString::formatted("{}", maybe_file.error()), {}, {}, {}, {}); return; } @@ -385,7 +385,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ if (maybe_data.is_error()) { log_failure(request, maybe_data.error()); if (error_callback) - error_callback->function()(ByteString::formatted("{}", maybe_data.error()), {}, {}, {}); + error_callback->function()(ByteString::formatted("{}", maybe_data.error()), {}, {}, {}, {}); return; } @@ -393,7 +393,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ auto response_headers = response_headers_for_file(URL::percent_decode(request.url().serialize_path()), st_or_error.value().st_mtime); log_success(request); - success_callback->function()(data, response_headers, {}); + success_callback->function()(data, response_headers, {}, {}); }); (*m_page)->client().request_file(move(file_request)); @@ -409,7 +409,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ auto protocol_request = start_network_request(request); if (!protocol_request) { if (error_callback) - error_callback->function()("Failed to start network request"sv, {}, {}, {}); + error_callback->function()("Failed to start network request"sv, {}, {}, {}, {}); return; } @@ -424,7 +424,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ timer->start(); } - auto on_buffered_request_finished = [this, success_callback, error_callback, request, &protocol_request = *protocol_request](auto, auto const& network_error, auto& response_headers, auto status_code, ReadonlyBytes payload) mutable { + auto on_buffered_request_finished = [this, success_callback, error_callback, request, &protocol_request = *protocol_request](auto, auto const& network_error, auto& response_headers, auto status_code, auto const& reason_phrase, ReadonlyBytes payload) mutable { handle_network_response_headers(request, response_headers); finish_network_request(protocol_request); @@ -440,12 +440,12 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ log_failure(request, error_builder.string_view()); if (error_callback) - error_callback->function()(error_builder.to_byte_string(), status_code, payload, response_headers); + error_callback->function()(error_builder.to_byte_string(), status_code, reason_phrase, payload, response_headers); return; } log_success(request); - success_callback->function()(payload, response_headers, status_code); + success_callback->function()(payload, response_headers, status_code, reason_phrase); }; protocol_request->set_buffered_request_finished_callback(move(on_buffered_request_finished)); @@ -455,7 +455,7 @@ void ResourceLoader::load(LoadRequest& request, JS::Handle succ auto not_implemented_error = ByteString::formatted("Protocol not implemented: {}", url.scheme()); log_failure(request, not_implemented_error); if (error_callback) - error_callback->function()(not_implemented_error, {}, {}, {}); + error_callback->function()(not_implemented_error, {}, {}, {}, {}); } void ResourceLoader::load_unbuffered(LoadRequest& request, JS::Handle on_headers_received, JS::Handle on_data_received, JS::Handle on_complete) @@ -482,9 +482,9 @@ void ResourceLoader::load_unbuffered(LoadRequest& request, JS::Handlefunction()(response_headers, move(status_code)); + on_headers_received->function()(response_headers, move(status_code), reason_phrase); }; auto protocol_data_received = [on_data_received](auto data) { diff --git a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h index b3617ac57a0..fb36eded0d4 100644 --- a/Userland/Libraries/LibWeb/Loader/ResourceLoader.h +++ b/Userland/Libraries/LibWeb/Loader/ResourceLoader.h @@ -26,13 +26,13 @@ public: RefPtr load_resource(Resource::Type, LoadRequest&); - using SuccessCallback = JS::HeapFunction status_code)>; - using ErrorCallback = JS::HeapFunction status_code, ReadonlyBytes payload, HTTP::HeaderMap const& response_headers)>; + using SuccessCallback = JS::HeapFunction status_code, Optional const& reason_phrase)>; + using ErrorCallback = JS::HeapFunction status_code, Optional const& reason_phrase, ReadonlyBytes payload, HTTP::HeaderMap const& response_headers)>; using TimeoutCallback = JS::HeapFunction; void load(LoadRequest&, JS::Handle success_callback, JS::Handle error_callback = nullptr, Optional timeout = {}, JS::Handle timeout_callback = nullptr); - using OnHeadersReceived = JS::HeapFunction status_code)>; + using OnHeadersReceived = JS::HeapFunction status_code, Optional const& reason_phrase)>; using OnDataReceived = JS::HeapFunction; using OnComplete = JS::HeapFunction error_message)>;