LibWeb: Partially implement 'Extract header (list) values' AOs

The header-specific ABNF rules are completely ignored for now, but we
can at least extract a single header value, which at least works for
simple cases like `Location`-based redirects.
This commit is contained in:
Linus Groh 2022-10-25 23:02:47 +01:00
parent 14e722617c
commit 455aa34011
Notes: sideshowbarker 2024-07-17 04:59:43 +09:00
2 changed files with 45 additions and 2 deletions

View file

@ -636,8 +636,49 @@ bool is_request_body_header_name(ReadonlyBytes header_name)
"Content-Type"sv);
}
// TODO: https://fetch.spec.whatwg.org/#extract-header-values
// TODO: https://fetch.spec.whatwg.org/#extract-header-list-values
// https://fetch.spec.whatwg.org/#extract-header-values
ErrorOr<Optional<Vector<ByteBuffer>>> extract_header_values(Header const& header)
{
// FIXME: 1. If parsing headers value, per the ABNF for headers name, fails, then return failure.
// FIXME: 2. Return one or more values resulting from parsing headers value, per the ABNF for headers name.
// 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)) };
}
// https://fetch.spec.whatwg.org/#extract-header-list-values
ErrorOr<Optional<Vector<ByteBuffer>>> extract_header_list_values(ReadonlyBytes name, HeaderList const& list)
{
// 1. If list does not contain name, then return null.
if (!list.contains(name))
return Optional<Vector<ByteBuffer>> {};
// FIXME: 2. If the ABNF for name allows a single header and list contains more than one, then return failure.
// NOTE: If different error handling is needed, extract the desired header first.
// 3. Let values be an empty list.
auto values = Vector<ByteBuffer> {};
// 4. For each header header list contains whose name is name:
for (auto const& header : list) {
if (!StringView { header.name }.equals_ignoring_case(name))
continue;
// 1. Let extract be the result of extracting header values from header.
auto extract = TRY(extract_header_values(header));
// 2. If extract is failure, then return failure.
// FIXME: Currently we treat the null return above and failure return as the same thing,
// ErrorOr already signals OOM to the caller.
if (!extract.has_value())
return Optional<Vector<ByteBuffer>> {};
// 3. Append each value in extract, in order, to values.
values.extend(extract.release_value());
}
// 5. Return values.
return values;
}
// https://fetch.spec.whatwg.org/#simple-range-header-value
Optional<RangeHeaderValue> parse_single_range_header_value(ReadonlyBytes value)

View file

@ -73,6 +73,8 @@ struct RangeHeaderValue {
[[nodiscard]] bool is_forbidden_header_name(ReadonlyBytes);
[[nodiscard]] bool is_forbidden_response_header_name(ReadonlyBytes);
[[nodiscard]] bool is_request_body_header_name(ReadonlyBytes);
[[nodiscard]] ErrorOr<Optional<Vector<ByteBuffer>>> extract_header_values(Header const&);
[[nodiscard]] ErrorOr<Optional<Vector<ByteBuffer>>> extract_header_list_values(ReadonlyBytes, HeaderList const&);
[[nodiscard]] Optional<RangeHeaderValue> parse_single_range_header_value(ReadonlyBytes);
[[nodiscard]] ErrorOr<ByteBuffer> default_user_agent_value();