Skip to content

Commit f675cfe

Browse files
committed
LibWeb: Store HTTP methods and headers as ByteString
The spec declares these as a byte sequence, which we then implemented as a ByteBuffer. This has become pretty awkward to deal with, as evidenced by the plethora of `MUST(ByteBuffer::copy(...))` and `.bytes()` calls everywhere inside Fetch. We would then treat the bytes as a string anyways by wrapping them in StringView everywhere. We now store these as a ByteString. This is more comfortable to deal with, and we no longer need to continually copy underlying storage (as ByteString is ref-counted). This work is largely preparatory for an upcoming HTTP header refactor.
1 parent ed27eea commit f675cfe

File tree

28 files changed

+481
-652
lines changed

28 files changed

+481
-652
lines changed

Libraries/LibWeb/ContentSecurityPolicy/Policy.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace Web::ContentSecurityPolicy {
2121
GC_DEFINE_ALLOCATOR(Policy);
2222

2323
// https://w3c.github.io/webappsec-csp/#abstract-opdef-parse-a-serialized-csp
24-
GC::Ref<Policy> Policy::parse_a_serialized_csp(GC::Heap& heap, Variant<ByteBuffer, String> serialized, Source source, Disposition disposition)
24+
GC::Ref<Policy> Policy::parse_a_serialized_csp(GC::Heap& heap, Variant<ByteString, String> serialized, Source source, Disposition disposition)
2525
{
2626
// To parse a serialized CSP, given a byte sequence or string serialized, a source source, and a disposition disposition,
2727
// execute the following steps.
@@ -31,7 +31,7 @@ GC::Ref<Policy> Policy::parse_a_serialized_csp(GC::Heap& heap, Variant<ByteBuffe
3131
// 1. If serialized is a byte sequence, then set serialized to be the result of isomorphic decoding serialized.
3232
auto serialized_string = serialized.has<String>()
3333
? serialized.get<String>()
34-
: Infra::isomorphic_decode(serialized.get<ByteBuffer>());
34+
: Infra::isomorphic_decode(serialized.get<ByteString>());
3535

3636
// 2. Let policy be a new policy with an empty directive set, a source of source, and a disposition of disposition.
3737
auto policy = heap.allocate<Policy>();
@@ -101,9 +101,9 @@ GC::Ref<PolicyList> Policy::parse_a_responses_content_security_policies(GC::Heap
101101

102102
// 2. For each token returned by extracting header list values given Content-Security-Policy and response’s header
103103
// list:
104-
auto enforce_policy_tokens_or_failure = response->header_list()->extract_header_list_values("Content-Security-Policy"sv.bytes());
104+
auto enforce_policy_tokens_or_failure = response->header_list()->extract_header_list_values("Content-Security-Policy"sv);
105105

106-
if (auto const* enforce_policy_tokens = enforce_policy_tokens_or_failure.get_pointer<Vector<ByteBuffer>>()) {
106+
if (auto const* enforce_policy_tokens = enforce_policy_tokens_or_failure.get_pointer<Vector<ByteString>>()) {
107107
for (auto const& enforce_policy_token : *enforce_policy_tokens) {
108108
// 1. Let policy be the result of parsing token, with a source of "header", and a disposition of "enforce".
109109
auto policy = parse_a_serialized_csp(heap, enforce_policy_token, Policy::Source::Header, Policy::Disposition::Enforce);
@@ -116,9 +116,9 @@ GC::Ref<PolicyList> Policy::parse_a_responses_content_security_policies(GC::Heap
116116

117117
// 3. For each token returned by extracting header list values given Content-Security-Policy-Report-Only and
118118
// response’s header list:
119-
auto report_policy_tokens_or_failure = response->header_list()->extract_header_list_values("Content-Security-Policy-Report-Only"sv.bytes());
119+
auto report_policy_tokens_or_failure = response->header_list()->extract_header_list_values("Content-Security-Policy-Report-Only"sv);
120120

121-
if (auto const* report_policy_tokens = enforce_policy_tokens_or_failure.get_pointer<Vector<ByteBuffer>>()) {
121+
if (auto const* report_policy_tokens = enforce_policy_tokens_or_failure.get_pointer<Vector<ByteString>>()) {
122122
for (auto const& report_policy_token : *report_policy_tokens) {
123123
// 1. Let policy be the result of parsing token, with a source of "header", and a disposition of "report".
124124
auto policy = parse_a_serialized_csp(heap, report_policy_token, Policy::Source::Header, Policy::Disposition::Report);

Libraries/LibWeb/ContentSecurityPolicy/Policy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Policy final : public GC::Cell {
3838

3939
~Policy() = default;
4040

41-
[[nodiscard]] static GC::Ref<Policy> parse_a_serialized_csp(GC::Heap&, Variant<ByteBuffer, String> serialized, Source source, Disposition disposition);
41+
[[nodiscard]] static GC::Ref<Policy> parse_a_serialized_csp(GC::Heap&, Variant<ByteString, String> serialized, Source source, Disposition disposition);
4242
[[nodiscard]] static GC::Ref<PolicyList> parse_a_responses_content_security_policies(GC::Heap&, GC::Ref<Fetch::Infrastructure::Response const> response);
4343
[[nodiscard]] static GC::Ref<Policy> create_from_serialized_policy(GC::Heap&, SerializedPolicy const&);
4444

Libraries/LibWeb/ContentSecurityPolicy/Violation.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ GC_DEFINE_ALLOCATOR(Violation);
2929
Violation::Violation(GC::Ptr<JS::Object> global_object, GC::Ref<Policy const> policy, String directive)
3030
: m_global_object(global_object)
3131
, m_policy(policy)
32-
, m_effective_directive(directive)
32+
, m_effective_directive(move(directive))
3333
{
3434
}
3535

@@ -38,7 +38,7 @@ GC::Ref<Violation> Violation::create_a_violation_object_for_global_policy_and_di
3838
{
3939
// 1. Let violation be a new violation whose global object is global, policy is policy, effective directive is
4040
// directive, and resource is null.
41-
auto violation = realm.create<Violation>(global_object, policy, directive);
41+
auto violation = realm.create<Violation>(global_object, policy, move(directive));
4242

4343
// FIXME: 2. If the user agent is currently executing script, and can extract a source file’s URL, line number,
4444
// and column number from the global, set violation’s source file, line number, and column number
@@ -406,7 +406,7 @@ void Violation::report_a_violation(JS::Realm& realm)
406406

407407
// method
408408
// "POST"
409-
request->set_method(MUST(ByteBuffer::copy("POST"sv.bytes())));
409+
request->set_method("POST"sv);
410410

411411
// url
412412
// violation’s url
@@ -448,8 +448,7 @@ void Violation::report_a_violation(JS::Realm& realm)
448448
// A header list containing a single header whose name is "Content-Type", and value is
449449
// "application/csp-report"
450450
auto header_list = Fetch::Infrastructure::HeaderList::create(vm);
451-
auto content_type_header = Fetch::Infrastructure::Header::from_string_pair("Content-Type"sv, "application/csp-report"sv);
452-
header_list->append(move(content_type_header));
451+
header_list->append({ "Content-Type"sv, "application/csp-report"sv });
453452
request->set_header_list(header_list);
454453

455454
// body

Libraries/LibWeb/DOM/Document.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,15 +385,15 @@ WebIDL::ExceptionOr<GC::Ref<Document>> Document::create_and_initialize(Type type
385385
document->m_window = window;
386386

387387
// NOTE: Non-standard: Pull out the Last-Modified header for use in the lastModified property.
388-
if (auto maybe_last_modified = navigation_params.response->header_list()->get("Last-Modified"sv.bytes()); maybe_last_modified.has_value()) {
388+
if (auto maybe_last_modified = navigation_params.response->header_list()->get("Last-Modified"sv); maybe_last_modified.has_value()) {
389389
// rfc9110, 8.8.2: The Last-Modified header field must be in GMT time zone.
390390
// document->m_last_modified is in local time zone.
391391
document->m_last_modified = AK::UnixDateTime::parse("%a, %d %b %Y %H:%M:%S GMT"sv, maybe_last_modified.value(), true);
392392
}
393393

394394
// NOTE: Non-standard: Pull out the Content-Language header to determine the document's language.
395-
if (auto maybe_http_content_language = navigation_params.response->header_list()->get("Content-Language"sv.bytes()); maybe_http_content_language.has_value()) {
396-
if (auto maybe_content_language = String::from_utf8(maybe_http_content_language.value()); !maybe_content_language.is_error())
395+
if (auto maybe_http_content_language = navigation_params.response->header_list()->get("Content-Language"sv); maybe_http_content_language.has_value()) {
396+
if (auto maybe_content_language = String::from_byte_string(maybe_http_content_language.value()); !maybe_content_language.is_error())
397397
document->m_http_content_language = maybe_content_language.release_value();
398398
}
399399

@@ -423,7 +423,7 @@ WebIDL::ExceptionOr<GC::Ref<Document>> Document::create_and_initialize(Type type
423423
// navigationParams's response's service worker timing info.
424424

425425
// 15. If navigationParams's response has a `Refresh` header, then:
426-
if (auto maybe_refresh = navigation_params.response->header_list()->get("Refresh"sv.bytes()); maybe_refresh.has_value()) {
426+
if (auto maybe_refresh = navigation_params.response->header_list()->get("Refresh"sv); maybe_refresh.has_value()) {
427427
// 1. Let value be the isomorphic decoding of the value of the header.
428428
auto value = Infra::isomorphic_decode(maybe_refresh.value());
429429

Libraries/LibWeb/Fetch/BodyInit.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
7272
Optional<u64> length {};
7373

7474
// 9. Let type be null.
75-
Optional<ByteBuffer> type {};
75+
Optional<ByteString> type {};
7676

7777
// 10. Switch on object.
7878
TRY(object.visit(
@@ -83,7 +83,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
8383
length = blob->size();
8484
// If object’s type attribute is not the empty byte sequence, set type to its value.
8585
if (!blob->type().is_empty())
86-
type = MUST(ByteBuffer::copy(blob->type().bytes()));
86+
type = blob->type().to_byte_string();
8787
return {};
8888
},
8989
[&](ReadonlyBytes bytes) -> WebIDL::ExceptionOr<void> {
@@ -103,24 +103,23 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
103103
source = serialized_form_data.serialized_data;
104104
// FIXME: Set length to unclear, see html/6424 for improving this.
105105
// Set type to `multipart/form-data; boundary=`, followed by the multipart/form-data boundary string generated by the multipart/form-data encoding algorithm.
106-
auto type_string = MUST(String::formatted("multipart/form-data; boundary={}", serialized_form_data.boundary));
107-
type = MUST(ByteBuffer::copy(type_string.bytes()));
106+
type = ByteString::formatted("multipart/form-data; boundary={}", serialized_form_data.boundary);
108107
return {};
109108
},
110109
[&](GC::Root<DOMURL::URLSearchParams> const& url_search_params) -> WebIDL::ExceptionOr<void> {
111110
// Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list.
112111
auto search_params_string = url_search_params->to_string();
113112
source = MUST(ByteBuffer::copy(search_params_string.bytes()));
114113
// Set type to `application/x-www-form-urlencoded;charset=UTF-8`.
115-
type = MUST(ByteBuffer::copy("application/x-www-form-urlencoded;charset=UTF-8"sv.bytes()));
114+
type = "application/x-www-form-urlencoded;charset=UTF-8"sv;
116115
return {};
117116
},
118117
[&](String const& scalar_value_string) -> WebIDL::ExceptionOr<void> {
119118
// NOTE: AK::String is always UTF-8.
120119
// Set source to the UTF-8 encoding of object.
121120
source = MUST(ByteBuffer::copy(scalar_value_string.bytes()));
122121
// Set type to `text/plain;charset=UTF-8`.
123-
type = MUST(ByteBuffer::copy("text/plain;charset=UTF-8"sv.bytes()));
122+
type = "text/plain;charset=UTF-8"sv;
124123
return {};
125124
},
126125
[&](GC::Root<Streams::ReadableStream> const& stream) -> WebIDL::ExceptionOr<void> {
@@ -169,7 +168,7 @@ WebIDL::ExceptionOr<Infrastructure::BodyWithType> extract_body(JS::Realm& realm,
169168
auto body = Infrastructure::Body::create(vm, *stream, move(source), move(length));
170169

171170
// 14. Return (body, type).
172-
return Infrastructure::BodyWithType { .body = move(body), .type = move(type) };
171+
return Infrastructure::BodyWithType { .body = body, .type = move(type) };
173172
}
174173

175174
}

Libraries/LibWeb/Fetch/Fetching/Checks.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ namespace Web::Fetch::Fetching {
1515
bool cors_check(Infrastructure::Request const& request, Infrastructure::Response const& response)
1616
{
1717
// 1. Let origin be the result of getting `Access-Control-Allow-Origin` from response’s header list.
18-
auto origin = response.header_list()->get("Access-Control-Allow-Origin"sv.bytes());
18+
auto origin = response.header_list()->get("Access-Control-Allow-Origin"sv);
1919

2020
// 2. If origin is null, then return failure.
2121
// NOTE: Null is not `null`.
2222
if (!origin.has_value())
2323
return false;
2424

2525
// 3. If request’s credentials mode is not "include" and origin is `*`, then return success.
26-
if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include && origin->span() == "*"sv.bytes())
26+
if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include && *origin == "*"sv)
2727
return true;
2828

2929
// 4. If the result of byte-serializing a request origin with request is not origin, then return failure.
@@ -35,10 +35,10 @@ bool cors_check(Infrastructure::Request const& request, Infrastructure::Response
3535
return true;
3636

3737
// 6. Let credentials be the result of getting `Access-Control-Allow-Credentials` from response’s header list.
38-
auto credentials = response.header_list()->get("Access-Control-Allow-Credentials"sv.bytes());
38+
auto credentials = response.header_list()->get("Access-Control-Allow-Credentials"sv);
3939

4040
// 7. If credentials is `true`, then return success.
41-
if (credentials.has_value() && credentials->span() == "true"sv.bytes())
41+
if (credentials == "true"sv)
4242
return true;
4343

4444
// 8. Return failure.
@@ -53,7 +53,7 @@ bool tao_check(Infrastructure::Request const& request, Infrastructure::Response
5353
return false;
5454

5555
// 2. Let values be the result of getting, decoding, and splitting `Timing-Allow-Origin` from response’s header list.
56-
auto values = response.header_list()->get_decode_and_split("Timing-Allow-Origin"sv.bytes());
56+
auto values = response.header_list()->get_decode_and_split("Timing-Allow-Origin"sv);
5757

5858
// 3. If values contains "*", then return success.
5959
if (values.has_value() && values->contains_slow("*"sv))

0 commit comments

Comments
 (0)