mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Extract some CORS and MIME Fetch helpers to their own files
An upcoming commit will migrate the contents of Headers.h/cpp to LibHTTP for use outside of LibWeb. These CORS and MIME helpers depend on other LibWeb facilities, however, so they cannot be moved.
This commit is contained in:
parent
0fd80a8f99
commit
3dce6766a3
Notes:
github-actions[bot]
2025-11-27 13:58:58 +00:00
Author: https://github.com/trflynn89
Commit: 3dce6766a3
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6944
Reviewed-by: https://github.com/gmta ✅
30 changed files with 382 additions and 299 deletions
|
|
@ -379,8 +379,10 @@ set(SOURCES
|
||||||
Fetch/Infrastructure/FetchTimingInfo.cpp
|
Fetch/Infrastructure/FetchTimingInfo.cpp
|
||||||
Fetch/Infrastructure/HTTP.cpp
|
Fetch/Infrastructure/HTTP.cpp
|
||||||
Fetch/Infrastructure/HTTP/Bodies.cpp
|
Fetch/Infrastructure/HTTP/Bodies.cpp
|
||||||
|
Fetch/Infrastructure/HTTP/CORS.cpp
|
||||||
Fetch/Infrastructure/HTTP/Headers.cpp
|
Fetch/Infrastructure/HTTP/Headers.cpp
|
||||||
Fetch/Infrastructure/HTTP/Methods.cpp
|
Fetch/Infrastructure/HTTP/Methods.cpp
|
||||||
|
Fetch/Infrastructure/HTTP/MIME.cpp
|
||||||
Fetch/Infrastructure/HTTP/Requests.cpp
|
Fetch/Infrastructure/HTTP/Requests.cpp
|
||||||
Fetch/Infrastructure/HTTP/Responses.cpp
|
Fetch/Infrastructure/HTTP/Responses.cpp
|
||||||
Fetch/Infrastructure/HTTP/Statuses.cpp
|
Fetch/Infrastructure/HTTP/Statuses.cpp
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include <LibWeb/CSS/StyleComputer.h>
|
#include <LibWeb/CSS/StyleComputer.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOMURL/DOMURL.h>
|
#include <LibWeb/DOMURL/DOMURL.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
|
|
||||||
|
|
@ -153,7 +154,7 @@ void CSSImportRule::fetch()
|
||||||
// 4. Let importedStylesheet be the result of parsing byteStream given parsedUrl.
|
// 4. Let importedStylesheet be the result of parsing byteStream given parsedUrl.
|
||||||
// FIXME: Tidy up our parsing API. For now, do the decoding here.
|
// FIXME: Tidy up our parsing API. For now, do the decoding here.
|
||||||
Optional<String> mime_type_charset;
|
Optional<String> mime_type_charset;
|
||||||
if (auto extracted_mime_type = response->header_list()->extract_mime_type(); extracted_mime_type.has_value()) {
|
if (auto extracted_mime_type = Fetch::Infrastructure::extract_mime_type(response->header_list()); extracted_mime_type.has_value()) {
|
||||||
if (auto charset = extracted_mime_type->parameters().get("charset"sv); charset.has_value())
|
if (auto charset = extracted_mime_type->parameters().get("charset"sv); charset.has_value())
|
||||||
mime_type_charset = charset.value();
|
mime_type_charset = charset.value();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
#include <LibWeb/DOM/ShadowRoot.h>
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Response.h>
|
#include <LibWeb/Fetch/Response.h>
|
||||||
#include <LibWeb/HTML/HTMLBRElement.h>
|
#include <LibWeb/HTML/HTMLBRElement.h>
|
||||||
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
||||||
|
|
@ -310,7 +311,7 @@ void FontLoader::font_did_load_or_fail(RefPtr<Gfx::Typeface const> typeface)
|
||||||
ErrorOr<NonnullRefPtr<Gfx::Typeface const>> FontLoader::try_load_font(Fetch::Infrastructure::Response const& response, ByteBuffer const& bytes)
|
ErrorOr<NonnullRefPtr<Gfx::Typeface const>> FontLoader::try_load_font(Fetch::Infrastructure::Response const& response, ByteBuffer const& bytes)
|
||||||
{
|
{
|
||||||
// FIXME: This could maybe use the format() provided in @font-face as well, since often the mime type is just application/octet-stream and we have to try every format
|
// FIXME: This could maybe use the format() provided in @font-face as well, since often the mime type is just application/octet-stream and we have to try every format
|
||||||
auto mime_type = response.header_list()->extract_mime_type();
|
auto mime_type = Fetch::Infrastructure::extract_mime_type(response.header_list());
|
||||||
if (!mime_type.has_value() || !mime_type->is_font()) {
|
if (!mime_type.has_value() || !mime_type->is_font()) {
|
||||||
mime_type = MimeSniff::Resource::sniff(bytes, MimeSniff::SniffingConfiguration { .sniffing_context = MimeSniff::SniffingContext::Font });
|
mime_type = MimeSniff::Resource::sniff(bytes, MimeSniff::SniffingConfiguration { .sniffing_context = MimeSniff::SniffingContext::Font });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <LibTextCodec/Decoder.h>
|
#include <LibTextCodec/Decoder.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/DocumentLoading.h>
|
#include <LibWeb/DOM/DocumentLoading.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/HTML/HTMLHeadElement.h>
|
#include <LibWeb/HTML/HTMLHeadElement.h>
|
||||||
#include <LibWeb/HTML/Navigable.h>
|
#include <LibWeb/HTML/Navigable.h>
|
||||||
#include <LibWeb/HTML/NavigationParams.h>
|
#include <LibWeb/HTML/NavigationParams.h>
|
||||||
|
|
@ -93,8 +94,8 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_html_document(HTML::Navi
|
||||||
// causes a load event to be fired.
|
// causes a load event to be fired.
|
||||||
else {
|
else {
|
||||||
// FIXME: Parse as we receive the document data, instead of waiting for the whole document to be fetched first.
|
// FIXME: Parse as we receive the document data, instead of waiting for the whole document to be fetched first.
|
||||||
auto process_body = GC::create_function(document->heap(), [document, signal_to_continue_session_history_processing, url = navigation_params.response->url().value(), mime_type = navigation_params.response->header_list()->extract_mime_type()](ByteBuffer data) {
|
auto process_body = GC::create_function(document->heap(), [document, signal_to_continue_session_history_processing, url = navigation_params.response->url().value(), mime_type = Fetch::Infrastructure::extract_mime_type(navigation_params.response->header_list())](ByteBuffer data) mutable {
|
||||||
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(document->heap(), [signal_to_continue_session_history_processing, document = document, data = move(data), url = url, mime_type] {
|
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(document->heap(), [signal_to_continue_session_history_processing, document = document, data = move(data), url = url, mime_type = move(mime_type)] {
|
||||||
// NB: If document is part of a session history entry's traversal, resolve the signal_to_continue_session_history_processing.
|
// NB: If document is part of a session history entry's traversal, resolve the signal_to_continue_session_history_processing.
|
||||||
signal_to_continue_session_history_processing->resolve({});
|
signal_to_continue_session_history_processing->resolve({});
|
||||||
auto parser = HTML::HTMLParser::create_with_uncertain_encoding(document, data, mime_type);
|
auto parser = HTML::HTMLParser::create_with_uncertain_encoding(document, data, mime_type);
|
||||||
|
|
@ -362,7 +363,7 @@ static WebIDL::ExceptionOr<GC::Ref<DOM::Document>> load_media_document(HTML::Nav
|
||||||
auto& realm = document->realm();
|
auto& realm = document->realm();
|
||||||
navigation_params.response->body()->fully_read(
|
navigation_params.response->body()->fully_read(
|
||||||
realm,
|
realm,
|
||||||
GC::create_function(document->heap(), [document, signal_to_continue_session_history_processing](ByteBuffer) {
|
GC::create_function(document->heap(), [document, signal_to_continue_session_history_processing](ByteBuffer) {
|
||||||
// NB: If document is part of session history traversal, resolve the signal_to_continue_session_history_processing.
|
// NB: If document is part of session history traversal, resolve the signal_to_continue_session_history_processing.
|
||||||
signal_to_continue_session_history_processing->resolve({});
|
signal_to_continue_session_history_processing->resolve({});
|
||||||
HTML::HTMLParser::the_end(document); }),
|
HTML::HTMLParser::the_end(document); }),
|
||||||
|
|
@ -418,7 +419,7 @@ GC::Ptr<DOM::Document> load_document(HTML::NavigationParams const& navigation_pa
|
||||||
// NB: Use Core::Promise to signal SessionHistoryTraversalQueue that it can continue to execute next entry.
|
// NB: Use Core::Promise to signal SessionHistoryTraversalQueue that it can continue to execute next entry.
|
||||||
|
|
||||||
// 1. Let type be the computed type of navigationParams's response.
|
// 1. Let type be the computed type of navigationParams's response.
|
||||||
auto supplied_type = navigation_params.response->header_list()->extract_mime_type();
|
auto supplied_type = Fetch::Infrastructure::extract_mime_type(navigation_params.response->header_list());
|
||||||
auto type = MimeSniff::Resource::sniff(
|
auto type = MimeSniff::Resource::sniff(
|
||||||
navigation_params.response->body()->source().visit(
|
navigation_params.response->body()->source().visit(
|
||||||
[](Empty) { return ReadonlyBytes {}; },
|
[](Empty) { return ReadonlyBytes {}; },
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchParams.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchParams.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchRecord.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchRecord.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchTimingInfo.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchTimingInfo.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/CORS.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
|
|
@ -713,7 +715,7 @@ void fetch_response_handover(JS::Realm& realm, Infrastructure::FetchParams const
|
||||||
response_status = response.status();
|
response_status = response.status();
|
||||||
|
|
||||||
// 2. Let mimeType be the result of extracting a MIME type from response’s header list.
|
// 2. Let mimeType be the result of extracting a MIME type from response’s header list.
|
||||||
auto mime_type = response.header_list()->extract_mime_type();
|
auto mime_type = Infrastructure::extract_mime_type(response.header_list());
|
||||||
|
|
||||||
// 3. If mimeType is non-null, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType.
|
// 3. If mimeType is non-null, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType.
|
||||||
if (mime_type.has_value())
|
if (mime_type.has_value())
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <LibWeb/Bindings/HeadersPrototype.h>
|
#include <LibWeb/Bindings/HeadersPrototype.h>
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
#include <LibWeb/Fetch/Headers.h>
|
#include <LibWeb/Fetch/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/CORS.h>
|
||||||
|
|
||||||
namespace Web::Fetch {
|
namespace Web::Fetch {
|
||||||
|
|
||||||
|
|
|
||||||
197
Libraries/LibWeb/Fetch/Infrastructure/HTTP/CORS.cpp
Normal file
197
Libraries/LibWeb/Fetch/Infrastructure/HTTP/CORS.cpp
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/Checked.h>
|
||||||
|
#include <LibHTTP/Header.h>
|
||||||
|
#include <LibTextCodec/Decoder.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/CORS.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/MimeSniff/MimeType.h>
|
||||||
|
|
||||||
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
|
||||||
|
bool is_cors_safelisted_request_header(Header const& header)
|
||||||
|
{
|
||||||
|
auto const& [name, value] = header;
|
||||||
|
|
||||||
|
// 1. If value’s length is greater than 128, then return false.
|
||||||
|
if (value.length() > 128)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 2. Byte-lowercase name and switch on the result:
|
||||||
|
// `accept`
|
||||||
|
if (name.equals_ignoring_ascii_case("accept"sv)) {
|
||||||
|
// If value contains a CORS-unsafe request-header byte, then return false.
|
||||||
|
if (any_of(value, is_cors_unsafe_request_header_byte))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// `accept-language`
|
||||||
|
// `content-language`
|
||||||
|
else if (name.is_one_of_ignoring_ascii_case("accept-language"sv, "content-language"sv)) {
|
||||||
|
// If value contains a byte that is not in the range 0x30 (0) to 0x39 (9), inclusive, is not in the range 0x41 (A) to 0x5A (Z), inclusive, is not in the range 0x61 (a) to 0x7A (z), inclusive, and is not 0x20 (SP), 0x2A (*), 0x2C (,), 0x2D (-), 0x2E (.), 0x3B (;), or 0x3D (=), then return false.
|
||||||
|
if (any_of(value, [](auto byte) {
|
||||||
|
return !(is_ascii_digit(byte) || is_ascii_alpha(byte) || " *,-.;="sv.contains(byte));
|
||||||
|
}))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// `content-type`
|
||||||
|
else if (name.equals_ignoring_ascii_case("content-type"sv)) {
|
||||||
|
// 1. If value contains a CORS-unsafe request-header byte, then return false.
|
||||||
|
if (any_of(value, is_cors_unsafe_request_header_byte))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 2. Let mimeType be the result of parsing the result of isomorphic decoding value.
|
||||||
|
auto decoded = TextCodec::isomorphic_decode(value);
|
||||||
|
auto mime_type = MimeSniff::MimeType::parse(decoded);
|
||||||
|
|
||||||
|
// 3. If mimeType is failure, then return false.
|
||||||
|
if (!mime_type.has_value())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 4. If mimeType’s essence is not "application/x-www-form-urlencoded", "multipart/form-data", or "text/plain", then return false.
|
||||||
|
if (!mime_type->essence().is_one_of("application/x-www-form-urlencoded"sv, "multipart/form-data"sv, "text/plain"sv))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// `range`
|
||||||
|
else if (name.equals_ignoring_ascii_case("range"sv)) {
|
||||||
|
// 1. Let rangeValue be the result of parsing a single range header value given value and false.
|
||||||
|
auto range_value = parse_single_range_header_value(value, false);
|
||||||
|
|
||||||
|
// 2. If rangeValue is failure, then return false.
|
||||||
|
if (!range_value.has_value())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 3. If rangeValue[0] is null, then return false.
|
||||||
|
// NOTE: As web browsers have historically not emitted ranges such as `bytes=-500` this algorithm does not safelist them.
|
||||||
|
if (!range_value->start.has_value())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Otherwise
|
||||||
|
else {
|
||||||
|
// Return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Return true.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte
|
||||||
|
bool is_cors_unsafe_request_header_byte(u8 byte)
|
||||||
|
{
|
||||||
|
// A CORS-unsafe request-header byte is a byte byte for which one of the following is true:
|
||||||
|
// - byte is less than 0x20 and is not 0x09 HT
|
||||||
|
// - byte is 0x22 ("), 0x28 (left parenthesis), 0x29 (right parenthesis), 0x3A (:), 0x3C (<), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), or 0x7F DEL.
|
||||||
|
return (byte < 0x20 && byte != 0x09)
|
||||||
|
|| (Array { 0x22, 0x28, 0x29, 0x3A, 0x3C, 0x3E, 0x3F, 0x40, 0x5B, 0x5C, 0x5D, 0x7B, 0x7D, 0x7F }.contains_slow(byte));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-names
|
||||||
|
Vector<ByteString> get_cors_unsafe_header_names(HeaderList const& headers)
|
||||||
|
{
|
||||||
|
// 1. Let unsafeNames be a new list.
|
||||||
|
Vector<ByteString> unsafe_names;
|
||||||
|
|
||||||
|
// 2. Let potentiallyUnsafeNames be a new list.
|
||||||
|
Vector<ByteString> potentially_unsafe_names;
|
||||||
|
|
||||||
|
// 3. Let safelistValueSize be 0.
|
||||||
|
Checked<size_t> safelist_value_size = 0;
|
||||||
|
|
||||||
|
// 4. For each header of headers:
|
||||||
|
for (auto const& header : headers) {
|
||||||
|
// 1. If header is not a CORS-safelisted request-header, then append header’s name to unsafeNames.
|
||||||
|
if (!is_cors_safelisted_request_header(header)) {
|
||||||
|
unsafe_names.append(header.name);
|
||||||
|
}
|
||||||
|
// 2. Otherwise, append header’s name to potentiallyUnsafeNames and increase safelistValueSize by header’s
|
||||||
|
// value’s length.
|
||||||
|
else {
|
||||||
|
potentially_unsafe_names.append(header.name);
|
||||||
|
safelist_value_size += header.value.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. If safelistValueSize is greater than 1024, then for each name of potentiallyUnsafeNames, append name to
|
||||||
|
// unsafeNames.
|
||||||
|
if (safelist_value_size.has_overflow() || safelist_value_size.value() > 1024)
|
||||||
|
unsafe_names.extend(move(potentially_unsafe_names));
|
||||||
|
|
||||||
|
// 6. Return the result of convert header names to a sorted-lowercase set with unsafeNames.
|
||||||
|
return convert_header_names_to_a_sorted_lowercase_set(unsafe_names.span());
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name
|
||||||
|
bool is_cors_non_wildcard_request_header_name(StringView header_name)
|
||||||
|
{
|
||||||
|
// A CORS non-wildcard request-header name is a header name that is a byte-case-insensitive match for `Authorization`.
|
||||||
|
return header_name.equals_ignoring_ascii_case("Authorization"sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#privileged-no-cors-request-header-name
|
||||||
|
bool is_privileged_no_cors_request_header_name(StringView header_name)
|
||||||
|
{
|
||||||
|
// A privileged no-CORS request-header name is a header name that is a byte-case-insensitive match for one of
|
||||||
|
// - `Range`.
|
||||||
|
return header_name.equals_ignoring_ascii_case("Range"sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
|
||||||
|
bool is_cors_safelisted_response_header_name(StringView header_name, ReadonlySpan<StringView> list)
|
||||||
|
{
|
||||||
|
// A CORS-safelisted response-header name, given a list of header names list, is a header name that is a byte-case-insensitive match for one of
|
||||||
|
// - `Cache-Control`
|
||||||
|
// - `Content-Language`
|
||||||
|
// - `Content-Length`
|
||||||
|
// - `Content-Type`
|
||||||
|
// - `Expires`
|
||||||
|
// - `Last-Modified`
|
||||||
|
// - `Pragma`
|
||||||
|
// - Any item in list that is not a forbidden response-header name.
|
||||||
|
return header_name.is_one_of_ignoring_ascii_case(
|
||||||
|
"Cache-Control"sv,
|
||||||
|
"Content-Language"sv,
|
||||||
|
"Content-Length"sv,
|
||||||
|
"Content-Type"sv,
|
||||||
|
"Expires"sv,
|
||||||
|
"Last-Modified"sv,
|
||||||
|
"Pragma"sv)
|
||||||
|
|| any_of(list, [&](auto list_header_name) {
|
||||||
|
return header_name.equals_ignoring_ascii_case(list_header_name)
|
||||||
|
&& !is_forbidden_response_header_name(list_header_name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header-name
|
||||||
|
bool is_no_cors_safelisted_request_header_name(StringView header_name)
|
||||||
|
{
|
||||||
|
// A no-CORS-safelisted request-header name is a header name that is a byte-case-insensitive match for one of
|
||||||
|
// - `Accept`
|
||||||
|
// - `Accept-Language`
|
||||||
|
// - `Content-Language`
|
||||||
|
// - `Content-Type`
|
||||||
|
return header_name.is_one_of_ignoring_ascii_case(
|
||||||
|
"Accept"sv,
|
||||||
|
"Accept-Language"sv,
|
||||||
|
"Content-Language"sv,
|
||||||
|
"Content-Type"sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header
|
||||||
|
bool is_no_cors_safelisted_request_header(Header const& header)
|
||||||
|
{
|
||||||
|
// 1. If name is not a no-CORS-safelisted request-header name, then return false.
|
||||||
|
if (!is_no_cors_safelisted_request_header_name(header.name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 2. Return whether (name, value) is a CORS-safelisted request-header.
|
||||||
|
return is_cors_safelisted_request_header(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
Libraries/LibWeb/Fetch/Infrastructure/HTTP/CORS.h
Normal file
25
Libraries/LibWeb/Fetch/Infrastructure/HTTP/CORS.h
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/ByteString.h>
|
||||||
|
#include <AK/StringView.h>
|
||||||
|
#include <AK/Vector.h>
|
||||||
|
#include <LibWeb/Forward.h>
|
||||||
|
|
||||||
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
||||||
|
[[nodiscard]] bool is_cors_safelisted_request_header(Header const&);
|
||||||
|
[[nodiscard]] bool is_cors_unsafe_request_header_byte(u8);
|
||||||
|
[[nodiscard]] Vector<ByteString> get_cors_unsafe_header_names(HeaderList const&);
|
||||||
|
[[nodiscard]] bool is_cors_non_wildcard_request_header_name(StringView);
|
||||||
|
[[nodiscard]] bool is_privileged_no_cors_request_header_name(StringView);
|
||||||
|
[[nodiscard]] bool is_cors_safelisted_response_header_name(StringView, ReadonlySpan<StringView>);
|
||||||
|
[[nodiscard]] bool is_no_cors_safelisted_request_header_name(StringView);
|
||||||
|
[[nodiscard]] bool is_no_cors_safelisted_request_header(Header const&);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
||||||
#include <LibWeb/Loader/ResourceLoader.h>
|
#include <LibWeb/Loader/ResourceLoader.h>
|
||||||
#include <LibWeb/MimeSniff/MimeType.h>
|
|
||||||
|
|
||||||
namespace Web::Fetch::Infrastructure {
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
||||||
|
|
@ -311,61 +310,6 @@ Variant<Empty, u64, HeaderList::ExtractLengthFailure> HeaderList::extract_length
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
|
|
||||||
Optional<MimeSniff::MimeType> HeaderList::extract_mime_type() const
|
|
||||||
{
|
|
||||||
// 1. Let charset be null.
|
|
||||||
Optional<String> charset;
|
|
||||||
|
|
||||||
// 2. Let essence be null.
|
|
||||||
Optional<String> essence;
|
|
||||||
|
|
||||||
// 3. Let mimeType be null.
|
|
||||||
Optional<MimeSniff::MimeType> mime_type;
|
|
||||||
|
|
||||||
// 4. Let values be the result of getting, decoding, and splitting `Content-Type` from headers.
|
|
||||||
auto values = get_decode_and_split("Content-Type"sv);
|
|
||||||
|
|
||||||
// 5. If values is null, then return failure.
|
|
||||||
if (!values.has_value())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
// 6. For each value of values:
|
|
||||||
for (auto const& value : *values) {
|
|
||||||
// 1. Let temporaryMimeType be the result of parsing value.
|
|
||||||
auto temporary_mime_type = MimeSniff::MimeType::parse(value);
|
|
||||||
|
|
||||||
// 2. If temporaryMimeType is failure or its essence is "*/*", then continue.
|
|
||||||
if (!temporary_mime_type.has_value() || temporary_mime_type->essence() == "*/*"sv)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// 3. Set mimeType to temporaryMimeType.
|
|
||||||
mime_type = temporary_mime_type;
|
|
||||||
|
|
||||||
// 4. If mimeType’s essence is not essence, then:
|
|
||||||
if (!essence.has_value() || (mime_type->essence() != essence->bytes_as_string_view())) {
|
|
||||||
// 1. Set charset to null.
|
|
||||||
charset = {};
|
|
||||||
|
|
||||||
// 2. If mimeType’s parameters["charset"] exists, then set charset to mimeType’s parameters["charset"].
|
|
||||||
auto it = mime_type->parameters().find("charset"sv);
|
|
||||||
if (it != mime_type->parameters().end())
|
|
||||||
charset = it->value;
|
|
||||||
|
|
||||||
// 3. Set essence to mimeType’s essence.
|
|
||||||
essence = mime_type->essence();
|
|
||||||
}
|
|
||||||
// 5. Otherwise, if mimeType’s parameters["charset"] does not exist, and charset is non-null, set mimeType’s parameters["charset"] to charset.
|
|
||||||
else if (!mime_type->parameters().contains("charset"sv) && charset.has_value()) {
|
|
||||||
mime_type->set_parameter("charset"_string, charset.release_value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. If mimeType is null, then return failure.
|
|
||||||
// 8. Return mimeType.
|
|
||||||
return mime_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-standard
|
// Non-standard
|
||||||
Vector<ByteString> HeaderList::unique_names() const
|
Vector<ByteString> HeaderList::unique_names() const
|
||||||
{
|
{
|
||||||
|
|
@ -494,29 +438,6 @@ bool is_forbidden_response_header_name(StringView header_name)
|
||||||
"Set-Cookie2"sv);
|
"Set-Cookie2"sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#legacy-extract-an-encoding
|
|
||||||
StringView legacy_extract_an_encoding(Optional<MimeSniff::MimeType> const& mime_type, StringView fallback_encoding)
|
|
||||||
{
|
|
||||||
// 1. If mimeType is failure, then return fallbackEncoding.
|
|
||||||
if (!mime_type.has_value())
|
|
||||||
return fallback_encoding;
|
|
||||||
|
|
||||||
// 2. If mimeType["charset"] does not exist, then return fallbackEncoding.
|
|
||||||
auto charset = mime_type->parameters().get("charset"sv);
|
|
||||||
if (!charset.has_value())
|
|
||||||
return fallback_encoding;
|
|
||||||
|
|
||||||
// 3. Let tentativeEncoding be the result of getting an encoding from mimeType["charset"].
|
|
||||||
auto tentative_encoding = TextCodec::get_standardized_encoding(*charset);
|
|
||||||
|
|
||||||
// 4. If tentativeEncoding is failure, then return fallbackEncoding.
|
|
||||||
if (!tentative_encoding.has_value())
|
|
||||||
return fallback_encoding;
|
|
||||||
|
|
||||||
// 5. Return tentativeEncoding.
|
|
||||||
return *tentative_encoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#header-value-get-decode-and-split
|
// https://fetch.spec.whatwg.org/#header-value-get-decode-and-split
|
||||||
Vector<String> get_decode_and_split_header_value(StringView value)
|
Vector<String> get_decode_and_split_header_value(StringView value)
|
||||||
{
|
{
|
||||||
|
|
@ -676,190 +597,6 @@ Optional<RangeHeaderValue> parse_single_range_header_value(StringView const valu
|
||||||
return RangeHeaderValue { move(range_start_value), move(range_end_value) };
|
return RangeHeaderValue { move(range_start_value), move(range_end_value) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
|
|
||||||
bool is_cors_safelisted_request_header(Header const& header)
|
|
||||||
{
|
|
||||||
// To determine whether a header (name, value) is a CORS-safelisted request-header, run these steps:
|
|
||||||
auto const& [name, value] = header;
|
|
||||||
|
|
||||||
// 1. If value’s length is greater than 128, then return false.
|
|
||||||
if (value.length() > 128)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// 2. Byte-lowercase name and switch on the result:
|
|
||||||
// `accept`
|
|
||||||
if (name.equals_ignoring_ascii_case("accept"sv)) {
|
|
||||||
// If value contains a CORS-unsafe request-header byte, then return false.
|
|
||||||
if (any_of(value, is_cors_unsafe_request_header_byte))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// `accept-language`
|
|
||||||
// `content-language`
|
|
||||||
else if (name.is_one_of_ignoring_ascii_case("accept-language"sv, "content-language"sv)) {
|
|
||||||
// If value contains a byte that is not in the range 0x30 (0) to 0x39 (9), inclusive, is not in the range 0x41 (A) to 0x5A (Z), inclusive, is not in the range 0x61 (a) to 0x7A (z), inclusive, and is not 0x20 (SP), 0x2A (*), 0x2C (,), 0x2D (-), 0x2E (.), 0x3B (;), or 0x3D (=), then return false.
|
|
||||||
if (any_of(value, [](auto byte) {
|
|
||||||
return !(is_ascii_digit(byte) || is_ascii_alpha(byte) || " *,-.;="sv.contains(byte));
|
|
||||||
}))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// `content-type`
|
|
||||||
else if (name.equals_ignoring_ascii_case("content-type"sv)) {
|
|
||||||
// 1. If value contains a CORS-unsafe request-header byte, then return false.
|
|
||||||
if (any_of(value, is_cors_unsafe_request_header_byte))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// 2. Let mimeType be the result of parsing the result of isomorphic decoding value.
|
|
||||||
auto decoded = TextCodec::isomorphic_decode(value);
|
|
||||||
auto mime_type = MimeSniff::MimeType::parse(decoded);
|
|
||||||
|
|
||||||
// 3. If mimeType is failure, then return false.
|
|
||||||
if (!mime_type.has_value())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// 4. If mimeType’s essence is not "application/x-www-form-urlencoded", "multipart/form-data", or "text/plain", then return false.
|
|
||||||
if (!mime_type->essence().is_one_of("application/x-www-form-urlencoded"sv, "multipart/form-data"sv, "text/plain"sv))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// `range`
|
|
||||||
else if (name.equals_ignoring_ascii_case("range"sv)) {
|
|
||||||
// 1. Let rangeValue be the result of parsing a single range header value given value and false.
|
|
||||||
auto range_value = parse_single_range_header_value(value, false);
|
|
||||||
|
|
||||||
// 2. If rangeValue is failure, then return false.
|
|
||||||
if (!range_value.has_value())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// 3. If rangeValue[0] is null, then return false.
|
|
||||||
// NOTE: As web browsers have historically not emitted ranges such as `bytes=-500` this algorithm does not safelist them.
|
|
||||||
if (!range_value->start.has_value())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Otherwise
|
|
||||||
else {
|
|
||||||
// Return false.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Return true.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte
|
|
||||||
bool is_cors_unsafe_request_header_byte(u8 byte)
|
|
||||||
{
|
|
||||||
// A CORS-unsafe request-header byte is a byte byte for which one of the following is true:
|
|
||||||
// - byte is less than 0x20 and is not 0x09 HT
|
|
||||||
// - byte is 0x22 ("), 0x28 (left parenthesis), 0x29 (right parenthesis), 0x3A (:), 0x3C (<), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), or 0x7F DEL.
|
|
||||||
return (byte < 0x20 && byte != 0x09)
|
|
||||||
|| (Array<u8, 14> { 0x22, 0x28, 0x29, 0x3A, 0x3C, 0x3E, 0x3F, 0x40, 0x5B, 0x5C, 0x5D, 0x7B, 0x7D, 0x7F }.span().contains_slow(byte));
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#cors-unsafe-request-header-names
|
|
||||||
Vector<ByteString> get_cors_unsafe_header_names(HeaderList const& headers)
|
|
||||||
{
|
|
||||||
// The CORS-unsafe request-header names, given a header list headers, are determined as follows:
|
|
||||||
|
|
||||||
// 1. Let unsafeNames be a new list.
|
|
||||||
Vector<ByteString> unsafe_names;
|
|
||||||
|
|
||||||
// 2. Let potentiallyUnsafeNames be a new list.
|
|
||||||
Vector<ByteString> potentially_unsafe_names;
|
|
||||||
|
|
||||||
// 3. Let safelistValueSize be 0.
|
|
||||||
Checked<size_t> safelist_value_size = 0;
|
|
||||||
|
|
||||||
// 4. For each header of headers:
|
|
||||||
for (auto const& header : headers) {
|
|
||||||
// 1. If header is not a CORS-safelisted request-header, then append header’s name to unsafeNames.
|
|
||||||
if (!is_cors_safelisted_request_header(header)) {
|
|
||||||
unsafe_names.append(header.name);
|
|
||||||
}
|
|
||||||
// 2. Otherwise, append header’s name to potentiallyUnsafeNames and increase safelistValueSize by header’s
|
|
||||||
// value’s length.
|
|
||||||
else {
|
|
||||||
potentially_unsafe_names.append(header.name);
|
|
||||||
safelist_value_size += header.value.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. If safelistValueSize is greater than 1024, then for each name of potentiallyUnsafeNames, append name to
|
|
||||||
// unsafeNames.
|
|
||||||
if (safelist_value_size.has_overflow() || safelist_value_size.value() > 1024)
|
|
||||||
unsafe_names.extend(move(potentially_unsafe_names));
|
|
||||||
|
|
||||||
// 6. Return the result of convert header names to a sorted-lowercase set with unsafeNames.
|
|
||||||
return convert_header_names_to_a_sorted_lowercase_set(unsafe_names);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name
|
|
||||||
bool is_cors_non_wildcard_request_header_name(StringView header_name)
|
|
||||||
{
|
|
||||||
// A CORS non-wildcard request-header name is a header name that is a byte-case-insensitive match for `Authorization`.
|
|
||||||
return header_name.equals_ignoring_ascii_case("Authorization"sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#privileged-no-cors-request-header-name
|
|
||||||
bool is_privileged_no_cors_request_header_name(StringView header_name)
|
|
||||||
{
|
|
||||||
// A privileged no-CORS request-header name is a header name that is a byte-case-insensitive match for one of
|
|
||||||
// - `Range`.
|
|
||||||
return header_name.equals_ignoring_ascii_case("Range"sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
|
|
||||||
bool is_cors_safelisted_response_header_name(StringView header_name, ReadonlySpan<StringView> list)
|
|
||||||
{
|
|
||||||
// A CORS-safelisted response-header name, given a list of header names list, is a header name that is a byte-case-insensitive match for one of
|
|
||||||
// - `Cache-Control`
|
|
||||||
// - `Content-Language`
|
|
||||||
// - `Content-Length`
|
|
||||||
// - `Content-Type`
|
|
||||||
// - `Expires`
|
|
||||||
// - `Last-Modified`
|
|
||||||
// - `Pragma`
|
|
||||||
// - Any item in list that is not a forbidden response-header name.
|
|
||||||
return header_name.is_one_of_ignoring_ascii_case(
|
|
||||||
"Cache-Control"sv,
|
|
||||||
"Content-Language"sv,
|
|
||||||
"Content-Length"sv,
|
|
||||||
"Content-Type"sv,
|
|
||||||
"Expires"sv,
|
|
||||||
"Last-Modified"sv,
|
|
||||||
"Pragma"sv)
|
|
||||||
|| any_of(list, [&](auto list_header_name) {
|
|
||||||
return header_name.equals_ignoring_ascii_case(list_header_name)
|
|
||||||
&& !is_forbidden_response_header_name(list_header_name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header-name
|
|
||||||
bool is_no_cors_safelisted_request_header_name(StringView header_name)
|
|
||||||
{
|
|
||||||
// A no-CORS-safelisted request-header name is a header name that is a byte-case-insensitive match for one of
|
|
||||||
// - `Accept`
|
|
||||||
// - `Accept-Language`
|
|
||||||
// - `Content-Language`
|
|
||||||
// - `Content-Type`
|
|
||||||
return header_name.is_one_of_ignoring_ascii_case(
|
|
||||||
"Accept"sv,
|
|
||||||
"Accept-Language"sv,
|
|
||||||
"Content-Language"sv,
|
|
||||||
"Content-Type"sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header
|
|
||||||
bool is_no_cors_safelisted_request_header(Header const& header)
|
|
||||||
{
|
|
||||||
// To determine whether a header (name, value) is a no-CORS-safelisted request-header, run these steps:
|
|
||||||
|
|
||||||
// 1. If name is not a no-CORS-safelisted request-header name, then return false.
|
|
||||||
if (!is_no_cors_safelisted_request_header_name(header.name))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// 2. Return whether (name, value) is a CORS-safelisted request-header.
|
|
||||||
return is_cors_safelisted_request_header(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#default-user-agent-value
|
// https://fetch.spec.whatwg.org/#default-user-agent-value
|
||||||
ByteString const& default_user_agent_value()
|
ByteString const& default_user_agent_value()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
#include <LibJS/Heap/Cell.h>
|
#include <LibJS/Heap/Cell.h>
|
||||||
#include <LibWeb/Export.h>
|
#include <LibWeb/Export.h>
|
||||||
#include <LibWeb/MimeSniff/MimeType.h>
|
|
||||||
|
|
||||||
namespace Web::Fetch::Infrastructure {
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
||||||
|
|
@ -61,8 +60,6 @@ public:
|
||||||
struct ExtractLengthFailure { };
|
struct ExtractLengthFailure { };
|
||||||
[[nodiscard]] Variant<Empty, u64, ExtractLengthFailure> extract_length() const;
|
[[nodiscard]] Variant<Empty, u64, ExtractLengthFailure> extract_length() const;
|
||||||
|
|
||||||
[[nodiscard]] Optional<MimeSniff::MimeType> extract_mime_type() const;
|
|
||||||
|
|
||||||
[[nodiscard]] Vector<ByteString> unique_names() const;
|
[[nodiscard]] Vector<ByteString> unique_names() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -78,22 +75,12 @@ struct RangeHeaderValue {
|
||||||
[[nodiscard]] bool is_forbidden_request_header(Header const&);
|
[[nodiscard]] bool is_forbidden_request_header(Header const&);
|
||||||
[[nodiscard]] bool is_forbidden_response_header_name(StringView);
|
[[nodiscard]] bool is_forbidden_response_header_name(StringView);
|
||||||
|
|
||||||
[[nodiscard]] WEB_API StringView legacy_extract_an_encoding(Optional<MimeSniff::MimeType> const& mime_type, StringView fallback_encoding);
|
|
||||||
[[nodiscard]] Vector<String> get_decode_and_split_header_value(StringView);
|
[[nodiscard]] Vector<String> get_decode_and_split_header_value(StringView);
|
||||||
[[nodiscard]] Vector<ByteString> convert_header_names_to_a_sorted_lowercase_set(ReadonlySpan<ByteString>);
|
[[nodiscard]] Vector<ByteString> convert_header_names_to_a_sorted_lowercase_set(ReadonlySpan<ByteString>);
|
||||||
|
|
||||||
[[nodiscard]] WEB_API ByteString build_content_range(u64 range_start, u64 range_end, u64 full_length);
|
[[nodiscard]] WEB_API ByteString build_content_range(u64 range_start, u64 range_end, u64 full_length);
|
||||||
[[nodiscard]] WEB_API Optional<RangeHeaderValue> parse_single_range_header_value(StringView, bool);
|
[[nodiscard]] WEB_API Optional<RangeHeaderValue> parse_single_range_header_value(StringView, bool);
|
||||||
|
|
||||||
[[nodiscard]] bool is_cors_safelisted_request_header(Header const&);
|
|
||||||
[[nodiscard]] bool is_cors_unsafe_request_header_byte(u8);
|
|
||||||
[[nodiscard]] WEB_API Vector<ByteString> get_cors_unsafe_header_names(HeaderList const&);
|
|
||||||
[[nodiscard]] WEB_API bool is_cors_non_wildcard_request_header_name(StringView);
|
|
||||||
[[nodiscard]] bool is_privileged_no_cors_request_header_name(StringView);
|
|
||||||
[[nodiscard]] bool is_cors_safelisted_response_header_name(StringView, ReadonlySpan<StringView>);
|
|
||||||
[[nodiscard]] bool is_no_cors_safelisted_request_header_name(StringView);
|
|
||||||
[[nodiscard]] bool is_no_cors_safelisted_request_header(Header const&);
|
|
||||||
|
|
||||||
[[nodiscard]] WEB_API ByteString const& default_user_agent_value();
|
[[nodiscard]] WEB_API ByteString const& default_user_agent_value();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
93
Libraries/LibWeb/Fetch/Infrastructure/HTTP/MIME.cpp
Normal file
93
Libraries/LibWeb/Fetch/Infrastructure/HTTP/MIME.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibTextCodec/Decoder.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
|
|
||||||
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
|
||||||
|
Optional<MimeSniff::MimeType> extract_mime_type(HeaderList const& headers)
|
||||||
|
{
|
||||||
|
// 1. Let charset be null.
|
||||||
|
Optional<String> charset;
|
||||||
|
|
||||||
|
// 2. Let essence be null.
|
||||||
|
Optional<String> essence;
|
||||||
|
|
||||||
|
// 3. Let mimeType be null.
|
||||||
|
Optional<MimeSniff::MimeType> mime_type;
|
||||||
|
|
||||||
|
// 4. Let values be the result of getting, decoding, and splitting `Content-Type` from headers.
|
||||||
|
auto values = headers.get_decode_and_split("Content-Type"sv);
|
||||||
|
|
||||||
|
// 5. If values is null, then return failure.
|
||||||
|
if (!values.has_value())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// 6. For each value of values:
|
||||||
|
for (auto const& value : *values) {
|
||||||
|
// 1. Let temporaryMimeType be the result of parsing value.
|
||||||
|
auto temporary_mime_type = MimeSniff::MimeType::parse(value);
|
||||||
|
|
||||||
|
// 2. If temporaryMimeType is failure or its essence is "*/*", then continue.
|
||||||
|
if (!temporary_mime_type.has_value() || temporary_mime_type->essence() == "*/*"sv)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// 3. Set mimeType to temporaryMimeType.
|
||||||
|
mime_type = temporary_mime_type;
|
||||||
|
|
||||||
|
// 4. If mimeType’s essence is not essence, then:
|
||||||
|
if (!essence.has_value() || (mime_type->essence() != *essence)) {
|
||||||
|
// 1. Set charset to null.
|
||||||
|
charset = {};
|
||||||
|
|
||||||
|
// 2. If mimeType’s parameters["charset"] exists, then set charset to mimeType’s parameters["charset"].
|
||||||
|
auto it = mime_type->parameters().find("charset"sv);
|
||||||
|
if (it != mime_type->parameters().end())
|
||||||
|
charset = it->value;
|
||||||
|
|
||||||
|
// 3. Set essence to mimeType’s essence.
|
||||||
|
essence = mime_type->essence();
|
||||||
|
}
|
||||||
|
// 5. Otherwise, if mimeType’s parameters["charset"] does not exist, and charset is non-null, set mimeType’s parameters["charset"] to charset.
|
||||||
|
else if (!mime_type->parameters().contains("charset"sv) && charset.has_value()) {
|
||||||
|
mime_type->set_parameter("charset"_string, charset.release_value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. If mimeType is null, then return failure.
|
||||||
|
// 8. Return mimeType.
|
||||||
|
return mime_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://fetch.spec.whatwg.org/#legacy-extract-an-encoding
|
||||||
|
StringView legacy_extract_an_encoding(Optional<MimeSniff::MimeType> const& mime_type, StringView fallback_encoding)
|
||||||
|
{
|
||||||
|
// 1. If mimeType is failure, then return fallbackEncoding.
|
||||||
|
if (!mime_type.has_value())
|
||||||
|
return fallback_encoding;
|
||||||
|
|
||||||
|
// 2. If mimeType["charset"] does not exist, then return fallbackEncoding.
|
||||||
|
auto charset = mime_type->parameters().get("charset"sv);
|
||||||
|
if (!charset.has_value())
|
||||||
|
return fallback_encoding;
|
||||||
|
|
||||||
|
// 3. Let tentativeEncoding be the result of getting an encoding from mimeType["charset"].
|
||||||
|
auto tentative_encoding = TextCodec::get_standardized_encoding(*charset);
|
||||||
|
|
||||||
|
// 4. If tentativeEncoding is failure, then return fallbackEncoding.
|
||||||
|
if (!tentative_encoding.has_value())
|
||||||
|
return fallback_encoding;
|
||||||
|
|
||||||
|
// 5. Return tentativeEncoding.
|
||||||
|
return *tentative_encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
Libraries/LibWeb/Fetch/Infrastructure/HTTP/MIME.h
Normal file
18
Libraries/LibWeb/Fetch/Infrastructure/HTTP/MIME.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Optional.h>
|
||||||
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWeb/MimeSniff/MimeType.h>
|
||||||
|
|
||||||
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
||||||
|
Optional<MimeSniff::MimeType> extract_mime_type(HeaderList const&);
|
||||||
|
StringView legacy_extract_an_encoding(Optional<MimeSniff::MimeType> const& mime_type, StringView fallback_encoding);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <LibWeb/DOMURL/DOMURL.h>
|
#include <LibWeb/DOMURL/DOMURL.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchParams.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchParams.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/CORS.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
|
|
||||||
namespace Web::Fetch::Infrastructure {
|
namespace Web::Fetch::Infrastructure {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/MimeTypeBlocking.h>
|
#include <LibWeb/Fetch/Infrastructure/MimeTypeBlocking.h>
|
||||||
|
|
@ -14,7 +15,7 @@ namespace Web::Fetch::Infrastructure {
|
||||||
RequestOrResponseBlocking should_response_to_request_be_blocked_due_to_its_mime_type(Response const& response, Request const& request)
|
RequestOrResponseBlocking should_response_to_request_be_blocked_due_to_its_mime_type(Response const& response, Request const& request)
|
||||||
{
|
{
|
||||||
// 1. Let mimeType be the result of extracting a MIME type from response’s header list.
|
// 1. Let mimeType be the result of extracting a MIME type from response’s header list.
|
||||||
auto mime_type = response.header_list()->extract_mime_type();
|
auto mime_type = Infrastructure::extract_mime_type(response.header_list());
|
||||||
|
|
||||||
// 2. If mimeType is failure, then return allowed.
|
// 2. If mimeType is failure, then return allowed.
|
||||||
if (!mime_type.has_value())
|
if (!mime_type.has_value())
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/NoSniffBlocking.h>
|
#include <LibWeb/Fetch/Infrastructure/NoSniffBlocking.h>
|
||||||
|
|
@ -38,7 +39,7 @@ RequestOrResponseBlocking should_response_to_request_be_blocked_due_to_nosniff(R
|
||||||
return RequestOrResponseBlocking::Allowed;
|
return RequestOrResponseBlocking::Allowed;
|
||||||
|
|
||||||
// 2. Let mimeType be the result of extracting a MIME type from response’s header list.
|
// 2. Let mimeType be the result of extracting a MIME type from response’s header list.
|
||||||
auto mime_type = response.header_list()->extract_mime_type();
|
auto mime_type = Infrastructure::extract_mime_type(response.header_list());
|
||||||
|
|
||||||
// 3. Let destination be request’s destination.
|
// 3. Let destination be request’s destination.
|
||||||
auto const& destination = request.destination();
|
auto const& destination = request.destination();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <LibWeb/Fetch/Headers.h>
|
#include <LibWeb/Fetch/Headers.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Request.h>
|
#include <LibWeb/Fetch/Request.h>
|
||||||
|
|
@ -51,7 +52,7 @@ Optional<MimeSniff::MimeType> Request::mime_type_impl() const
|
||||||
{
|
{
|
||||||
// Objects including the Body interface mixin need to define an associated MIME type algorithm which takes no arguments and returns failure or a MIME type.
|
// Objects including the Body interface mixin need to define an associated MIME type algorithm which takes no arguments and returns failure or a MIME type.
|
||||||
// A Request object’s MIME type is to return the result of extracting a MIME type from its request’s header list.
|
// A Request object’s MIME type is to return the result of extracting a MIME type from its request’s header list.
|
||||||
return m_request->header_list()->extract_mime_type();
|
return Infrastructure::extract_mime_type(m_request->header_list());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#concept-body-body
|
// https://fetch.spec.whatwg.org/#concept-body-body
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <LibWeb/DOMURL/DOMURL.h>
|
#include <LibWeb/DOMURL/DOMURL.h>
|
||||||
#include <LibWeb/Fetch/Enums.h>
|
#include <LibWeb/Fetch/Enums.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h>
|
||||||
#include <LibWeb/Fetch/Response.h>
|
#include <LibWeb/Fetch/Response.h>
|
||||||
|
|
@ -48,7 +49,7 @@ Optional<MimeSniff::MimeType> Response::mime_type_impl() const
|
||||||
{
|
{
|
||||||
// Objects including the Body interface mixin need to define an associated MIME type algorithm which takes no arguments and returns failure or a MIME type.
|
// Objects including the Body interface mixin need to define an associated MIME type algorithm which takes no arguments and returns failure or a MIME type.
|
||||||
// A Response object’s MIME type is to return the result of extracting a MIME type from its response’s header list.
|
// A Response object’s MIME type is to return the result of extracting a MIME type from its response’s header list.
|
||||||
return m_response->header_list()->extract_mime_type();
|
return Infrastructure::extract_mime_type(m_response->header_list());
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://fetch.spec.whatwg.org/#concept-body-body
|
// https://fetch.spec.whatwg.org/#concept-body-body
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/HTML/CORSSettingAttribute.h>
|
#include <LibWeb/HTML/CORSSettingAttribute.h>
|
||||||
|
|
@ -100,7 +101,7 @@ WebIDL::ExceptionOr<GC::Ref<EventSource>> EventSource::construct_impl(JS::Realm&
|
||||||
response = response->unsafe_response();
|
response = response->unsafe_response();
|
||||||
|
|
||||||
auto content_type_is_text_event_stream = [&]() {
|
auto content_type_is_text_event_stream = [&]() {
|
||||||
auto content_type = response->header_list()->extract_mime_type();
|
auto content_type = Fetch::Infrastructure::extract_mime_type(response->header_list());
|
||||||
if (!content_type.has_value())
|
if (!content_type.has_value())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/HTML/EventNames.h>
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
|
|
@ -778,7 +779,7 @@ void HTMLLinkElement::process_stylesheet_resource(bool success, Fetch::Infrastru
|
||||||
// 1. If the resource's Content-Type metadata is not text/css, then set success to false.
|
// 1. If the resource's Content-Type metadata is not text/css, then set success to false.
|
||||||
auto mime_type_string = m_mime_type;
|
auto mime_type_string = m_mime_type;
|
||||||
Optional<String> mime_type_charset;
|
Optional<String> mime_type_charset;
|
||||||
auto extracted_mime_type = response.header_list()->extract_mime_type();
|
auto extracted_mime_type = Fetch::Infrastructure::extract_mime_type(response.header_list());
|
||||||
if (extracted_mime_type.has_value()) {
|
if (extracted_mime_type.has_value()) {
|
||||||
if (!mime_type_string.has_value())
|
if (!mime_type_string.has_value())
|
||||||
mime_type_string = extracted_mime_type->essence();
|
mime_type_string = extracted_mime_type->essence();
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/HTML/DecodedImageData.h>
|
#include <LibWeb/HTML/DecodedImageData.h>
|
||||||
#include <LibWeb/HTML/HTMLMediaElement.h>
|
#include <LibWeb/HTML/HTMLMediaElement.h>
|
||||||
|
|
@ -361,7 +362,7 @@ void HTMLObjectElement::resource_did_load(Fetch::Infrastructure::Response const&
|
||||||
|
|
||||||
// 3. Run the appropriate set of steps from the following list:
|
// 3. Run the appropriate set of steps from the following list:
|
||||||
// -> If the resource has associated Content-Type metadata
|
// -> If the resource has associated Content-Type metadata
|
||||||
if (auto content_type = response.header_list()->extract_mime_type(); content_type.has_value()) {
|
if (auto content_type = Fetch::Infrastructure::extract_mime_type(response.header_list()); content_type.has_value()) {
|
||||||
// 1. Let binary be false.
|
// 1. Let binary be false.
|
||||||
bool binary = false;
|
bool binary = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/CORS.h>
|
||||||
#include <LibWeb/HTML/Navigator.h>
|
#include <LibWeb/HTML/Navigator.h>
|
||||||
#include <LibWeb/HTML/NavigatorBeacon.h>
|
#include <LibWeb/HTML/NavigatorBeacon.h>
|
||||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <LibTextCodec/Decoder.h>
|
#include <LibTextCodec/Decoder.h>
|
||||||
#include <LibWeb/DOM/Attr.h>
|
#include <LibWeb/DOM/Attr.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/HTML/Parser/HTMLEncodingDetection.h>
|
#include <LibWeb/HTML/Parser/HTMLEncodingDetection.h>
|
||||||
#include <LibWeb/Infra/CharacterTypes.h>
|
#include <LibWeb/Infra/CharacterTypes.h>
|
||||||
|
|
||||||
|
|
@ -444,7 +445,7 @@ Optional<ByteString> run_bom_sniff(ReadonlyBytes input)
|
||||||
// Byte order mark Encoding
|
// Byte order mark Encoding
|
||||||
// 0xEF 0xBB 0xBF UTF-8
|
// 0xEF 0xBB 0xBF UTF-8
|
||||||
// 0xFE 0xFF UTF-16BE
|
// 0xFE 0xFF UTF-16BE
|
||||||
// 0xFF 0xFE UTF-16LE
|
// 0xFF 0xFE UTF-16LE
|
||||||
if (input[0] == 0xEF && input[1] == 0xBB && input[2] == 0xBF) {
|
if (input[0] == 0xEF && input[1] == 0xBB && input[2] == 0xBF) {
|
||||||
return "UTF-8";
|
return "UTF-8";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <LibGC/Ptr.h>
|
#include <LibGC/Ptr.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWeb/MimeSniff/MimeType.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/URL.h>
|
#include <LibWeb/Fetch/Infrastructure/URL.h>
|
||||||
|
|
@ -360,7 +361,7 @@ void fetch_classic_script(GC::Ref<HTMLScriptElement> element, URL::URL const& ur
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Let potentialMIMETypeForEncoding be the result of extracting a MIME type given response's header list.
|
// 3. Let potentialMIMETypeForEncoding be the result of extracting a MIME type given response's header list.
|
||||||
auto potential_mime_type_for_encoding = response->header_list()->extract_mime_type();
|
auto potential_mime_type_for_encoding = Fetch::Infrastructure::extract_mime_type(response->header_list());
|
||||||
|
|
||||||
// 4. Set character encoding to the result of legacy extracting an encoding given potentialMIMETypeForEncoding
|
// 4. Set character encoding to the result of legacy extracting an encoding given potentialMIMETypeForEncoding
|
||||||
// and character encoding.
|
// and character encoding.
|
||||||
|
|
@ -427,7 +428,7 @@ WebIDL::ExceptionOr<void> fetch_classic_worker_script(URL::URL const& url, Envir
|
||||||
// 3. If all of the following are true:
|
// 3. If all of the following are true:
|
||||||
// - response's URL's scheme is an HTTP(S) scheme; and
|
// - response's URL's scheme is an HTTP(S) scheme; and
|
||||||
// - the result of extracting a MIME type from response's header list is not a JavaScript MIME type,
|
// - the result of extracting a MIME type from response's header list is not a JavaScript MIME type,
|
||||||
auto maybe_mime_type = response->header_list()->extract_mime_type();
|
auto maybe_mime_type = Fetch::Infrastructure::extract_mime_type(response->header_list());
|
||||||
auto mime_type_is_javascript = maybe_mime_type.has_value() && maybe_mime_type->is_javascript();
|
auto mime_type_is_javascript = maybe_mime_type.has_value() && maybe_mime_type->is_javascript();
|
||||||
|
|
||||||
if (response->url().has_value() && Fetch::Infrastructure::is_http_or_https_scheme(response->url()->scheme()) && !mime_type_is_javascript) {
|
if (response->url().has_value() && Fetch::Infrastructure::is_http_or_https_scheme(response->url()->scheme()) && !mime_type_is_javascript) {
|
||||||
|
|
@ -527,7 +528,7 @@ WebIDL::ExceptionOr<GC::Ref<ClassicScript>> fetch_a_classic_worker_imported_scri
|
||||||
// then throw a "NetworkError" DOMException.
|
// then throw a "NetworkError" DOMException.
|
||||||
if (body_bytes.template has<Empty>() || body_bytes.template has<Fetch::Infrastructure::FetchAlgorithms::ConsumeBodyFailureTag>()
|
if (body_bytes.template has<Empty>() || body_bytes.template has<Fetch::Infrastructure::FetchAlgorithms::ConsumeBodyFailureTag>()
|
||||||
|| !Fetch::Infrastructure::is_ok_status(response->status())
|
|| !Fetch::Infrastructure::is_ok_status(response->status())
|
||||||
|| !response->header_list()->extract_mime_type().has_value() || !response->header_list()->extract_mime_type()->is_javascript()) {
|
|| !Fetch::Infrastructure::extract_mime_type(response->header_list()).has_value() || !Fetch::Infrastructure::extract_mime_type(response->header_list())->is_javascript()) {
|
||||||
return WebIDL::NetworkError::create(realm, "Network error"_utf16);
|
return WebIDL::NetworkError::create(realm, "Network error"_utf16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,7 +703,7 @@ void fetch_single_module_script(JS::Realm& realm,
|
||||||
auto source_text = TextCodec::convert_input_to_utf8_using_given_decoder_unless_there_is_a_byte_order_mark(*decoder, body_bytes.get<ByteBuffer>()).release_value_but_fixme_should_propagate_errors();
|
auto source_text = TextCodec::convert_input_to_utf8_using_given_decoder_unless_there_is_a_byte_order_mark(*decoder, body_bytes.get<ByteBuffer>()).release_value_but_fixme_should_propagate_errors();
|
||||||
|
|
||||||
// 3. Let mimeType be the result of extracting a MIME type from response's header list.
|
// 3. Let mimeType be the result of extracting a MIME type from response's header list.
|
||||||
auto mime_type = response->header_list()->extract_mime_type();
|
auto mime_type = Fetch::Infrastructure::extract_mime_type(response->header_list());
|
||||||
|
|
||||||
// 4. Let moduleScript be null.
|
// 4. Let moduleScript be null.
|
||||||
GC::Ptr<JavaScriptModuleScript> module_script;
|
GC::Ptr<JavaScriptModuleScript> module_script;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h>
|
||||||
#include <LibWeb/HTML/AnimatedBitmapDecodedImageData.h>
|
#include <LibWeb/HTML/AnimatedBitmapDecodedImageData.h>
|
||||||
|
|
@ -87,7 +88,7 @@ void SharedResourceRequest::fetch_resource(JS::Realm& realm, GC::Ref<Fetch::Infr
|
||||||
response = response->unsafe_response();
|
response = response->unsafe_response();
|
||||||
|
|
||||||
auto process_body = GC::create_function(heap(), [this, request, response](ByteBuffer data) {
|
auto process_body = GC::create_function(heap(), [this, request, response](ByteBuffer data) {
|
||||||
auto extracted_mime_type = response->header_list()->extract_mime_type();
|
auto extracted_mime_type = Fetch::Infrastructure::extract_mime_type(response->header_list());
|
||||||
auto mime_type = extracted_mime_type.has_value() ? extracted_mime_type.value().essence().bytes_as_string_view() : StringView {};
|
auto mime_type = extracted_mime_type.has_value() ? extracted_mime_type.value().essence().bytes_as_string_view() : StringView {};
|
||||||
handle_successful_fetch(request->url(), mime_type, move(data));
|
handle_successful_fetch(request->url(), mime_type, move(data));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <LibWeb/MediaCapabilitiesAPI/MediaCapabilities.h>
|
#include <LibWeb/MediaCapabilitiesAPI/MediaCapabilities.h>
|
||||||
|
#include <LibWeb/MimeSniff/MimeType.h>
|
||||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||||
|
|
||||||
namespace Web::MediaCapabilitiesAPI {
|
namespace Web::MediaCapabilitiesAPI {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||||
|
#include <LibWeb/MimeSniff/MimeType.h>
|
||||||
#include <LibWeb/Namespace.h>
|
#include <LibWeb/Namespace.h>
|
||||||
#include <LibWeb/SVG/AttributeNames.h>
|
#include <LibWeb/SVG/AttributeNames.h>
|
||||||
#include <LibWeb/SVG/SVGScriptElement.h>
|
#include <LibWeb/SVG/SVGScriptElement.h>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <LibWeb/DOMURL/DOMURL.h>
|
#include <LibWeb/DOMURL/DOMURL.h>
|
||||||
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
#include <LibWeb/Fetch/Fetching/Fetching.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Response.h>
|
#include <LibWeb/Fetch/Response.h>
|
||||||
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
#include <LibWeb/HTML/Scripting/ClassicScript.h>
|
||||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||||
|
|
@ -254,7 +255,7 @@ static void update(JS::VM& vm, GC::Ref<Job> job)
|
||||||
|
|
||||||
fetch_algorithms_input.process_response = [request, job, state, newest_worker, &realm, ®istration, &process_response_completion_result](GC::Ref<Fetch::Infrastructure::Response> response) mutable -> void {
|
fetch_algorithms_input.process_response = [request, job, state, newest_worker, &realm, ®istration, &process_response_completion_result](GC::Ref<Fetch::Infrastructure::Response> response) mutable -> void {
|
||||||
// 7. Extract a MIME type from the response’s header list. If s MIME type (ignoring parameters) is not a JavaScript MIME type, then:
|
// 7. Extract a MIME type from the response’s header list. If s MIME type (ignoring parameters) is not a JavaScript MIME type, then:
|
||||||
auto mime_type = response->header_list()->extract_mime_type();
|
auto mime_type = Fetch::Infrastructure::extract_mime_type(response->header_list());
|
||||||
if (!mime_type.has_value() || !mime_type->is_javascript()) {
|
if (!mime_type.has_value() || !mime_type->is_javascript()) {
|
||||||
// 1. Invoke Reject Job Promise with job and "SecurityError" DOMException.
|
// 1. Invoke Reject Job Promise with job and "SecurityError" DOMException.
|
||||||
reject_job_promise<WebIDL::SecurityError>(job, "Service Worker script response is not a JavaScript MIME type"_utf16);
|
reject_job_promise<WebIDL::SecurityError>(job, "Service Worker script response is not a JavaScript MIME type"_utf16);
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
#include <LibWeb/Bindings/ResponsePrototype.h>
|
#include <LibWeb/Bindings/ResponsePrototype.h>
|
||||||
#include <LibWeb/ContentSecurityPolicy/BlockingAlgorithms.h>
|
#include <LibWeb/ContentSecurityPolicy/BlockingAlgorithms.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Response.h>
|
#include <LibWeb/Fetch/Response.h>
|
||||||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||||
|
|
@ -891,7 +892,7 @@ GC::Ref<WebIDL::Promise> compile_potential_webassembly_response(JS::VM& vm, GC::
|
||||||
// 5. If mimeType is not a byte-case-insensitive match for `application/wasm`, reject returnValue with a TypeError and abort these substeps.
|
// 5. If mimeType is not a byte-case-insensitive match for `application/wasm`, reject returnValue with a TypeError and abort these substeps.
|
||||||
// Note: extra parameters are not allowed, including the empty `application/wasm;`.
|
// Note: extra parameters are not allowed, including the empty `application/wasm;`.
|
||||||
// FIXME: Validate these extra constraints that are not checked by extract_mime_type()
|
// FIXME: Validate these extra constraints that are not checked by extract_mime_type()
|
||||||
if (auto mime = response->header_list()->extract_mime_type(); !mime.has_value() || mime.value().essence() != "application/wasm"sv) {
|
if (auto mime = Fetch::Infrastructure::extract_mime_type(response->header_list()); !mime.has_value() || mime.value().essence() != "application/wasm"sv) {
|
||||||
WebIDL::reject_promise(realm, return_value, vm.throw_completion<JS::TypeError>("Response does not match the application/wasm MIME type"sv).value());
|
WebIDL::reject_promise(realm, return_value, vm.throw_completion<JS::TypeError>("Response does not match the application/wasm MIME type"sv).value());
|
||||||
return JS::js_undefined();
|
return JS::js_undefined();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchAlgorithms.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
#include <LibWeb/Fetch/Infrastructure/FetchController.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP.h>
|
||||||
|
#include <LibWeb/Fetch/Infrastructure/HTTP/MIME.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
|
||||||
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
|
||||||
|
|
@ -366,7 +367,7 @@ MimeSniff::MimeType XMLHttpRequest::get_final_mime_type() const
|
||||||
MimeSniff::MimeType XMLHttpRequest::get_response_mime_type() const
|
MimeSniff::MimeType XMLHttpRequest::get_response_mime_type() const
|
||||||
{
|
{
|
||||||
// 1. Let mimeType be the result of extracting a MIME type from xhr’s response’s header list.
|
// 1. Let mimeType be the result of extracting a MIME type from xhr’s response’s header list.
|
||||||
auto mime_type = m_response->header_list()->extract_mime_type();
|
auto mime_type = Fetch::Infrastructure::extract_mime_type(m_response->header_list());
|
||||||
|
|
||||||
// 2. If mimeType is failure, then set mimeType to text/xml.
|
// 2. If mimeType is failure, then set mimeType to text/xml.
|
||||||
if (!mime_type.has_value())
|
if (!mime_type.has_value())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue