mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:37:46 +00:00
LibWeb: Implement Headers.getSetCookie()
This is a normative change in the Fetch spec.
See: 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
This commit is contained in:
parent
6bce48e99b
commit
ee68eba0ac
4 changed files with 53 additions and 13 deletions
|
@ -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
|
* 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 {};
|
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
|
// https://fetch.spec.whatwg.org/#dom-headers-has
|
||||||
WebIDL::ExceptionOr<bool> Headers::has(DeprecatedString const& name_string)
|
WebIDL::ExceptionOr<bool> Headers::has(DeprecatedString const& name_string)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -50,6 +50,7 @@ public:
|
||||||
WebIDL::ExceptionOr<void> append(DeprecatedString const& name, DeprecatedString const& value);
|
WebIDL::ExceptionOr<void> append(DeprecatedString const& name, DeprecatedString const& value);
|
||||||
WebIDL::ExceptionOr<void> delete_(DeprecatedString const& name);
|
WebIDL::ExceptionOr<void> delete_(DeprecatedString const& name);
|
||||||
WebIDL::ExceptionOr<DeprecatedString> get(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<bool> has(DeprecatedString const& name);
|
||||||
WebIDL::ExceptionOr<void> set(DeprecatedString const& name, DeprecatedString const& value);
|
WebIDL::ExceptionOr<void> set(DeprecatedString const& name, DeprecatedString const& value);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ interface Headers {
|
||||||
undefined append(ByteString name, ByteString value);
|
undefined append(ByteString name, ByteString value);
|
||||||
undefined delete(ByteString name);
|
undefined delete(ByteString name);
|
||||||
ByteString? get(ByteString name);
|
ByteString? get(ByteString name);
|
||||||
|
sequence<ByteString> getSetCookie();
|
||||||
boolean has(ByteString name);
|
boolean has(ByteString name);
|
||||||
undefined set(ByteString name, ByteString value);
|
undefined set(ByteString name, ByteString value);
|
||||||
iterable<ByteString, ByteString>;
|
iterable<ByteString, ByteString>;
|
||||||
|
|
|
@ -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, Kenneth Myhra <kennethmyhra@serenityos.org>
|
||||||
* Copyright (c) 2022, Luke Wilde <lukew@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.
|
// 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;
|
Vector<ReadonlyBytes> names_list;
|
||||||
|
TRY(names_list.try_ensure_capacity(size()));
|
||||||
for (auto const& header : *this)
|
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));
|
auto names = TRY(convert_header_names_to_a_sorted_lowercase_set(names_list));
|
||||||
|
|
||||||
// 3. For each name of names:
|
// 3. For each name of names:
|
||||||
for (auto& name : names) {
|
for (auto& name : names) {
|
||||||
// 1. Let value be the result of getting name from list.
|
// 1. If name is `set-cookie`, then:
|
||||||
// 2. Assert: value is not null.
|
if (name == "set-cookie"sv.bytes()) {
|
||||||
auto value = TRY(get(name)).value();
|
// 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));
|
||||||
|
|
||||||
// 3. Append (name, value) to headers.
|
// 2. Assert: value is not null.
|
||||||
auto header = Infrastructure::Header {
|
VERIFY(value.has_value());
|
||||||
.name = move(name),
|
|
||||||
.value = move(value),
|
// 3. Append (name, value) to headers.
|
||||||
};
|
auto header = Header {
|
||||||
headers.append(move(header));
|
.name = move(name),
|
||||||
|
.value = value.release_value(),
|
||||||
|
};
|
||||||
|
TRY(headers.try_append(move(header)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Return headers.
|
// 4. Return headers.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue