From 2ce416a676c8da185e709d9ea8fc9b38be871f8e Mon Sep 17 00:00:00 2001 From: Simon McMahon Date: Tue, 1 Aug 2023 22:00:28 +1200 Subject: [PATCH] LibWeb: Parse header value lists for some CORS headers This adds a simple and incomplete implementation for extracting some specific CORS headers that are used by fetch. This unifies the existing ad-hoc parsing that already existed for Access-Control-Allow-Headers and Access-Control-Allow-Methods, as well as adding Access-control-Expose-Headers. --- .../LibWeb/Fetch/Fetching/Fetching.cpp | 32 ------------------- .../Fetch/Infrastructure/HTTP/Headers.cpp | 20 ++++++++++++ 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index a046a5822d..8a4a9aec4d 100644 --- a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -1812,38 +1812,6 @@ WebIDL::ExceptionOr> cors_preflight_fetch(JS:: // NOTE: We treat "header_names_or_failure" being `Empty` as empty Vector here. auto header_names = header_names_or_failure.has>() ? header_names_or_failure.get>() : Vector {}; - // FIXME: Remove this once extract_header_list_values validates the header and returns multiple values. - if (!methods.is_empty()) { - VERIFY(methods.size() == 1); - - auto split_methods = StringView { methods.first() }.split_view(','); - Vector trimmed_methods; - - for (auto const& method : split_methods) { - auto trimmed_method = method.trim(" \t"sv); - auto trimmed_method_as_byte_buffer = TRY_OR_IGNORE(ByteBuffer::copy(trimmed_method.bytes())); - TRY_OR_IGNORE(trimmed_methods.try_append(move(trimmed_method_as_byte_buffer))); - } - - methods = move(trimmed_methods); - } - - // FIXME: Remove this once extract_header_list_values validates the header and returns multiple values. - if (!header_names.is_empty()) { - VERIFY(header_names.size() == 1); - - auto split_header_names = StringView { header_names.first() }.split_view(','); - Vector trimmed_header_names; - - for (auto const& header_name : split_header_names) { - auto trimmed_header_name = header_name.trim(" \t"sv); - auto trimmed_header_name_as_byte_buffer = TRY_OR_IGNORE(ByteBuffer::copy(trimmed_header_name.bytes())); - TRY_OR_IGNORE(trimmed_header_names.try_append(move(trimmed_header_name_as_byte_buffer))); - } - - header_names = move(trimmed_header_names); - } - // 4. If methods is null and request’s use-CORS-preflight flag is set, then set methods to a new list containing request’s method. // NOTE: This ensures that a CORS-preflight fetch that happened due to request’s use-CORS-preflight flag being set is cached. if (methods.is_empty() && request.use_cors_preflight()) diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp index 5d8d2869a1..ffbc12f0fa 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp @@ -776,6 +776,26 @@ ErrorOr>> extract_header_values(Header const& header { // FIXME: 1. If parsing header’s value, per the ABNF for header’s name, fails, then return failure. // FIXME: 2. Return one or more values resulting from parsing header’s value, per the ABNF for header’s name. + + // For now we only parse some headers that are of the ABNF list form "#something" + if (StringView { header.name }.is_one_of_ignoring_ascii_case( + "Access-Control-Request-Headers"sv, + "Access-Control-Expose-Headers"sv, + "Access-Control-Allow-Headers"sv, + "Access-Control-Allow-Methods"sv) + && !header.value.is_empty()) { + auto split_values = StringView { header.value }.split_view(','); + Vector trimmed_values; + + for (auto const& value : split_values) { + auto trimmed_value = value.trim(" \t"sv); + auto trimmed_value_as_byte_buffer = TRY(ByteBuffer::copy(trimmed_value.bytes())); + TRY(trimmed_values.try_append(move(trimmed_value_as_byte_buffer))); + } + + return trimmed_values; + } + // This always ignores the ABNF rules for now and returns the header value as a single list item. return Vector { TRY(ByteBuffer::copy(header.value)) }; }