summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2023-02-10 22:02:18 +0000
committerLinus Groh <mail@linusgroh.de>2023-02-11 13:14:26 +0000
commitee68eba0acc380a3b52efb3ed4bddffdab2eceaa (patch)
tree7f5edaef9157cb5deffc140389fc741731203fcb /Userland
parent6bce48e99bf7bc325f4047a20828bb8099025dad (diff)
downloadserenity-ee68eba0acc380a3b52efb3ed4bddffdab2eceaa.zip
LibWeb: Implement Headers.getSetCookie()
This is a normative change in the Fetch spec. See: https://github.com/whatwg/fetch/commit/e4d3480 This also implements the changes to the 'sort and combine' algorithm, which now treats "set-cookie" headers differently, and is exposed to JS via the Headers' iterator. Passes all 21 WPT tests :^) http://wpt.live/fetch/api/headers/header-setcookie.any.html
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibWeb/Fetch/Headers.cpp22
-rw-r--r--Userland/Libraries/LibWeb/Fetch/Headers.h3
-rw-r--r--Userland/Libraries/LibWeb/Fetch/Headers.idl1
-rw-r--r--Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp42
4 files changed, 54 insertions, 14 deletions
diff --git a/Userland/Libraries/LibWeb/Fetch/Headers.cpp b/Userland/Libraries/LibWeb/Fetch/Headers.cpp
index 0441b5d8d8..7aae86b938 100644
--- a/Userland/Libraries/LibWeb/Fetch/Headers.cpp
+++ b/Userland/Libraries/LibWeb/Fetch/Headers.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -112,6 +112,26 @@ WebIDL::ExceptionOr<DeprecatedString> Headers::get(DeprecatedString const& name_
return byte_buffer.has_value() ? DeprecatedString { byte_buffer->span() } : DeprecatedString {};
}
+// https://fetch.spec.whatwg.org/#dom-headers-getsetcookie
+WebIDL::ExceptionOr<Vector<DeprecatedString>> Headers::get_set_cookie()
+{
+ // The getSetCookie() method steps are:
+ auto& vm = this->vm();
+ auto values = Vector<DeprecatedString> {};
+
+ // 1. If this’s header list does not contain `Set-Cookie`, then return « ».
+ if (!m_header_list->contains("Set-Cookie"sv.bytes()))
+ return values;
+
+ // 2. Return the values of all headers in this’s header list whose name is a byte-case-insensitive match for
+ // `Set-Cookie`, in order.
+ for (auto const& header : *m_header_list) {
+ if (StringView { header.name }.equals_ignoring_case("Set-Cookie"sv))
+ TRY_OR_THROW_OOM(vm, values.try_append(DeprecatedString { header.value.bytes() }));
+ }
+ return values;
+}
+
// https://fetch.spec.whatwg.org/#dom-headers-has
WebIDL::ExceptionOr<bool> Headers::has(DeprecatedString const& name_string)
{
diff --git a/Userland/Libraries/LibWeb/Fetch/Headers.h b/Userland/Libraries/LibWeb/Fetch/Headers.h
index 683a4f7327..c366b5fcbf 100644
--- a/Userland/Libraries/LibWeb/Fetch/Headers.h
+++ b/Userland/Libraries/LibWeb/Fetch/Headers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -50,6 +50,7 @@ public:
WebIDL::ExceptionOr<void> append(DeprecatedString const& name, DeprecatedString const& value);
WebIDL::ExceptionOr<void> delete_(DeprecatedString const& name);
WebIDL::ExceptionOr<DeprecatedString> get(DeprecatedString const& name);
+ WebIDL::ExceptionOr<Vector<DeprecatedString>> get_set_cookie();
WebIDL::ExceptionOr<bool> has(DeprecatedString const& name);
WebIDL::ExceptionOr<void> set(DeprecatedString const& name, DeprecatedString const& value);
diff --git a/Userland/Libraries/LibWeb/Fetch/Headers.idl b/Userland/Libraries/LibWeb/Fetch/Headers.idl
index f2dbd9e4c0..a495339dd5 100644
--- a/Userland/Libraries/LibWeb/Fetch/Headers.idl
+++ b/Userland/Libraries/LibWeb/Fetch/Headers.idl
@@ -7,6 +7,7 @@ interface Headers {
undefined append(ByteString name, ByteString value);
undefined delete(ByteString name);
ByteString? get(ByteString name);
+ sequence<ByteString> getSetCookie();
boolean has(ByteString name);
undefined set(ByteString name, ByteString value);
iterable<ByteString, ByteString>;
diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp
index 2b5addf6fd..abc8d56889 100644
--- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp
+++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Headers.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, Kenneth Myhra <kennethmyhra@serenityos.org>
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
*
@@ -257,22 +257,40 @@ ErrorOr<Vector<Header>> HeaderList::sort_and_combine() const
// 2. Let names be the result of convert header names to a sorted-lowercase set with all the names of the headers in list.
Vector<ReadonlyBytes> names_list;
+ TRY(names_list.try_ensure_capacity(size()));
for (auto const& header : *this)
- names_list.append(header.name);
+ names_list.unchecked_append(header.name);
auto names = TRY(convert_header_names_to_a_sorted_lowercase_set(names_list));
// 3. For each name of names:
for (auto& name : names) {
- // 1. Let value be the result of getting name from list.
- // 2. Assert: value is not null.
- auto value = TRY(get(name)).value();
-
- // 3. Append (name, value) to headers.
- auto header = Infrastructure::Header {
- .name = move(name),
- .value = move(value),
- };
- headers.append(move(header));
+ // 1. If name is `set-cookie`, then:
+ if (name == "set-cookie"sv.bytes()) {
+ // 1. Let values be a list of all values of headers in list whose name is a byte-case-insensitive match for name, in order.
+ // 2. For each value of values:
+ for (auto const& [header_name, value] : *this) {
+ if (StringView { header_name }.equals_ignoring_case(name)) {
+ // 1. Append (name, value) to headers.
+ auto header = TRY(Header::from_string_pair(name, value));
+ TRY(headers.try_append(move(header)));
+ }
+ }
+ }
+ // 2. Otherwise:
+ else {
+ // 1. Let value be the result of getting name from list.
+ auto value = TRY(get(name));
+
+ // 2. Assert: value is not null.
+ VERIFY(value.has_value());
+
+ // 3. Append (name, value) to headers.
+ auto header = Header {
+ .name = move(name),
+ .value = value.release_value(),
+ };
+ TRY(headers.try_append(move(header)));
+ }
}
// 4. Return headers.