123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656 |
- /*
- * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/URLParser.h>
- #include <LibJS/Runtime/Completion.h>
- #include <LibWeb/Bindings/Intrinsics.h>
- #include <LibWeb/Bindings/RequestPrototype.h>
- #include <LibWeb/DOM/AbortSignal.h>
- #include <LibWeb/Fetch/Enums.h>
- #include <LibWeb/Fetch/Headers.h>
- #include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
- #include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
- #include <LibWeb/Fetch/Infrastructure/HTTP/Methods.h>
- #include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
- #include <LibWeb/Fetch/Request.h>
- #include <LibWeb/HTML/Scripting/Environments.h>
- #include <LibWeb/ReferrerPolicy/ReferrerPolicy.h>
- namespace Web::Fetch {
- Request::Request(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Request> request)
- : PlatformObject(realm)
- , m_request(request)
- {
- }
- Request::~Request() = default;
- JS::ThrowCompletionOr<void> Request::initialize(JS::Realm& realm)
- {
- MUST_OR_THROW_OOM(Base::initialize(realm));
- set_prototype(&Bindings::ensure_web_prototype<Bindings::RequestPrototype>(realm, "Request"));
- return {};
- }
- void Request::visit_edges(Cell::Visitor& visitor)
- {
- Base::visit_edges(visitor);
- visitor.visit(m_request);
- visitor.visit(m_headers);
- visitor.visit(m_signal);
- }
- // https://fetch.spec.whatwg.org/#concept-body-mime-type
- // https://fetch.spec.whatwg.org/#ref-for-concept-body-mime-type%E2%91%A0
- ErrorOr<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.
- // 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();
- }
- // https://fetch.spec.whatwg.org/#concept-body-body
- // https://fetch.spec.whatwg.org/#ref-for-concept-body-body%E2%91%A7
- Optional<Infrastructure::Body const&> Request::body_impl() const
- {
- // Objects including the Body interface mixin have an associated body (null or a body).
- // A Request object’s body is its request’s body.
- return m_request->body().visit(
- [](Infrastructure::Body const& b) -> Optional<Infrastructure::Body const&> { return b; },
- [](Empty) -> Optional<Infrastructure::Body const&> { return {}; },
- // A byte sequence will be safely extracted into a body early on in fetch.
- [](ByteBuffer const&) -> Optional<Infrastructure::Body const&> { VERIFY_NOT_REACHED(); });
- }
- // https://fetch.spec.whatwg.org/#concept-body-body
- // https://fetch.spec.whatwg.org/#ref-for-concept-body-body%E2%91%A7
- Optional<Infrastructure::Body&> Request::body_impl()
- {
- // Objects including the Body interface mixin have an associated body (null or a body).
- // A Request object’s body is its request’s body.
- return m_request->body().visit(
- [](Infrastructure::Body& b) -> Optional<Infrastructure::Body&> { return b; },
- [](Empty) -> Optional<Infrastructure::Body&> { return {}; },
- // A byte sequence will be safely extracted into a body early on in fetch.
- [](ByteBuffer&) -> Optional<Infrastructure::Body&> { VERIFY_NOT_REACHED(); });
- }
- // https://fetch.spec.whatwg.org/#request-create
- WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::create(JS::Realm& realm, JS::NonnullGCPtr<Infrastructure::Request> request, Headers::Guard guard)
- {
- // 1. Let requestObject be a new Request object with realm.
- // 2. Set requestObject’s request to request.
- auto request_object = MUST_OR_THROW_OOM(realm.heap().allocate<Request>(realm, realm, request));
- // 3. Set requestObject’s headers to a new Headers object with realm, whose headers list is request’s headers list and guard is guard.
- request_object->m_headers = MUST_OR_THROW_OOM(realm.heap().allocate<Headers>(realm, realm, request->header_list()));
- request_object->m_headers->set_guard(guard);
- // 4. Set requestObject’s signal to a new AbortSignal object with realm.
- request_object->m_signal = MUST_OR_THROW_OOM(realm.heap().allocate<DOM::AbortSignal>(realm, realm));
- // 5. Return requestObject.
- return request_object;
- }
- // https://fetch.spec.whatwg.org/#dom-request
- WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::construct_impl(JS::Realm& realm, RequestInfo const& input, RequestInit const& init)
- {
- auto& vm = realm.vm();
- // Referred to as 'this' in the spec.
- auto request_object = MUST_OR_THROW_OOM(realm.heap().allocate<Request>(realm, realm, Infrastructure::Request::create(vm)));
- // 1. Let request be null.
- JS::GCPtr<Infrastructure::Request> input_request;
- // 2. Let fallbackMode be null.
- Optional<Infrastructure::Request::Mode> fallback_mode;
- // 3. Let baseURL be this’s relevant settings object’s API base URL.
- auto base_url = HTML::relevant_settings_object(*request_object).api_base_url();
- // 4. Let signal be null.
- DOM::AbortSignal* input_signal = nullptr;
- // 5. If input is a string, then:
- if (input.has<String>()) {
- // 1. Let parsedURL be the result of parsing input with baseURL.
- auto parsed_url = URLParser::parse(input.get<String>(), base_url);
- // 2. If parsedURL is failure, then throw a TypeError.
- if (!parsed_url.is_valid())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Input URL is not valid"sv };
- // 3. If parsedURL includes credentials, then throw a TypeError.
- if (parsed_url.includes_credentials())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Input URL must not include credentials"sv };
- // 4. Set request to a new request whose URL is parsedURL.
- input_request = Infrastructure::Request::create(vm);
- input_request->set_url(move(parsed_url));
- // 5. Set fallbackMode to "cors".
- fallback_mode = Infrastructure::Request::Mode::CORS;
- }
- // 6. Otherwise:
- else {
- // 1. Assert: input is a Request object.
- VERIFY(input.has<JS::Handle<Request>>());
- // 2. Set request to input’s request.
- input_request = input.get<JS::Handle<Request>>()->request();
- // 3. Set signal to input’s signal.
- input_signal = input.get<JS::Handle<Request>>()->signal();
- }
- // 7. Let origin be this’s relevant settings object’s origin.
- auto const& origin = HTML::relevant_settings_object(*request_object).origin();
- // 8. Let window be "client".
- auto window = Infrastructure::Request::WindowType { Infrastructure::Request::Window::Client };
- // 9. If request’s window is an environment settings object and its origin is same origin with origin, then set window to request’s window.
- if (input_request->window().has<JS::GCPtr<HTML::EnvironmentSettingsObject>>()) {
- auto eso = input_request->window().get<JS::GCPtr<HTML::EnvironmentSettingsObject>>();
- if (eso->origin().is_same_origin(origin))
- window = input_request->window();
- }
- // 10. If init["window"] exists and is non-null, then throw a TypeError.
- if (init.window.has_value() && !init.window->is_null())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "The 'window' property must be omitted or null"sv };
- // 11. If init["window"] exists, then set window to "no-window".
- if (init.window.has_value())
- window = Infrastructure::Request::Window::NoWindow;
- // 12. Set request to a new request with the following properties:
- // NOTE: This is done at the beginning as the 'this' value Request object
- // cannot exist with a null Infrastructure::Request.
- auto request = request_object->request();
- // URL
- // request’s URL.
- request->set_url(input_request->url());
- // method
- // request’s method.
- request->set_method(TRY_OR_THROW_OOM(vm, ByteBuffer::copy(input_request->method())));
- // header list
- // A copy of request’s header list.
- auto header_list_copy = Infrastructure::HeaderList::create(vm);
- for (auto& header : *input_request->header_list())
- TRY_OR_THROW_OOM(vm, header_list_copy->append(header));
- request->set_header_list(header_list_copy);
- // unsafe-request flag
- // Set.
- request->set_unsafe_request(true);
- // client
- // This’s relevant settings object.
- request->set_client(&HTML::relevant_settings_object(*request_object));
- // window
- // window.
- request->set_window(window);
- // priority
- // request’s priority.
- request->set_priority(input_request->priority());
- // origin
- // request’s origin. The propagation of the origin is only significant for navigation requests being handled by a service worker. In this scenario a request can have an origin that is different from the current client.
- request->set_origin(input_request->origin());
- // referrer
- // request’s referrer.
- request->set_referrer(input_request->referrer());
- // referrer policy
- // request’s referrer policy.
- request->set_referrer_policy(input_request->referrer_policy());
- // mode
- // request’s mode.
- request->set_mode(input_request->mode());
- // credentials mode
- // request’s credentials mode.
- request->set_credentials_mode(input_request->credentials_mode());
- // cache mode
- // request’s cache mode.
- request->set_cache_mode(input_request->cache_mode());
- // redirect mode
- // request’s redirect mode.
- request->set_redirect_mode(input_request->redirect_mode());
- // integrity metadata
- // request’s integrity metadata.
- request->set_integrity_metadata(input_request->integrity_metadata());
- // keepalive
- // request’s keepalive.
- request->set_keepalive(input_request->keepalive());
- // reload-navigation flag
- // request’s reload-navigation flag.
- request->set_reload_navigation(input_request->reload_navigation());
- // history-navigation flag
- // request’s history-navigation flag.
- request->set_history_navigation(input_request->history_navigation());
- // URL list
- // A clone of request’s URL list.
- request->set_url_list(input_request->url_list());
- // initiator type
- // "fetch".
- request->set_initiator_type(Infrastructure::Request::InitiatorType::Fetch);
- // 13. If init is not empty, then:
- if (!init.is_empty()) {
- // 1. If request’s mode is "navigate", then set it to "same-origin".
- if (request->mode() == Infrastructure::Request::Mode::Navigate)
- request->set_mode(Infrastructure::Request::Mode::SameOrigin);
- // 2. Unset request’s reload-navigation flag.
- request->set_reload_navigation(false);
- // 3. Unset request’s history-navigation flag.
- request->set_history_navigation(false);
- // 4. Set request’s origin to "client".
- request->set_origin(Infrastructure::Request::Origin::Client);
- // 5. Set request’s referrer to "client".
- request->set_referrer(Infrastructure::Request::Referrer::Client);
- // 6. Set request’s referrer policy to the empty string.
- request->set_referrer_policy({});
- // 7. Set request’s URL to request’s current URL.
- request->set_url(request->current_url());
- // 8. Set request’s URL list to « request’s URL ».
- // NOTE: This is done implicitly by assigning the initial URL above.
- }
- // 14. If init["referrer"] exists, then:
- if (init.referrer.has_value()) {
- // 1. Let referrer be init["referrer"].
- auto const& referrer = *init.referrer;
- // 2. If referrer is the empty string, then set request’s referrer to "no-referrer".
- if (referrer.is_empty()) {
- request->set_referrer(Infrastructure::Request::Referrer::NoReferrer);
- }
- // 3. Otherwise:
- else {
- // 1. Let parsedReferrer be the result of parsing referrer with baseURL.
- auto parsed_referrer = URLParser::parse(referrer, base_url);
- // 2. If parsedReferrer is failure, then throw a TypeError.
- if (!parsed_referrer.is_valid())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Referrer must be a valid URL"sv };
- // 3. If one of the following is true
- // - parsedReferrer’s scheme is "about" and path is the string "client"
- // - parsedReferrer’s origin is not same origin with origin
- // then set request’s referrer to "client".
- // FIXME: Actually use the given origin once we have https://url.spec.whatwg.org/#concept-url-origin.
- if ((parsed_referrer.scheme() == "about"sv && parsed_referrer.path() == "client"sv) || !HTML::Origin().is_same_origin(origin)) {
- request->set_referrer(Infrastructure::Request::Referrer::Client);
- }
- // 4. Otherwise, set request’s referrer to parsedReferrer.
- else {
- request->set_referrer(move(parsed_referrer));
- }
- }
- }
- // 15. If init["referrerPolicy"] exists, then set request’s referrer policy to it.
- if (init.referrer_policy.has_value())
- request->set_referrer_policy(from_bindings_enum(*init.referrer_policy));
- // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise.
- auto mode = init.mode.has_value()
- ? from_bindings_enum(*init.mode)
- : fallback_mode;
- // 17. If mode is "navigate", then throw a TypeError.
- if (mode == Infrastructure::Request::Mode::Navigate)
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Mode must not be 'navigate"sv };
- // 18. If mode is non-null, set request’s mode to mode.
- if (mode.has_value())
- request->set_mode(*mode);
- // 19. If init["credentials"] exists, then set request’s credentials mode to it.
- if (init.credentials.has_value())
- request->set_credentials_mode(from_bindings_enum(*init.credentials));
- // 20. If init["cache"] exists, then set request’s cache mode to it.
- if (init.cache.has_value())
- request->set_cache_mode(from_bindings_enum(*init.cache));
- // 21. If request’s cache mode is "only-if-cached" and request’s mode is not "same-origin", then throw a TypeError.
- if (request->cache_mode() == Infrastructure::Request::CacheMode::OnlyIfCached && request->mode() != Infrastructure::Request::Mode::SameOrigin)
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Mode must be 'same-origin' when cache mode is 'only-if-cached'"sv };
- // 22. If init["redirect"] exists, then set request’s redirect mode to it.
- if (init.redirect.has_value())
- request->set_redirect_mode(from_bindings_enum(*init.redirect));
- // 23. If init["integrity"] exists, then set request’s integrity metadata to it.
- if (init.integrity.has_value())
- request->set_integrity_metadata(*init.integrity);
- // 24. If init["keepalive"] exists, then set request’s keepalive to it.
- if (init.keepalive.has_value())
- request->set_keepalive(*init.keepalive);
- // 25. If init["method"] exists, then:
- if (init.method.has_value()) {
- // 1. Let method be init["method"].
- auto method = *init.method;
- // 2. If method is not a method or method is a forbidden method, then throw a TypeError.
- if (!Infrastructure::is_method(method.bytes()))
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method has invalid value"sv };
- if (Infrastructure::is_forbidden_method(method.bytes()))
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method must not be one of CONNECT, TRACE, or TRACK"sv };
- // 3. Normalize method.
- method = TRY_OR_THROW_OOM(vm, String::from_utf8(TRY_OR_THROW_OOM(vm, Infrastructure::normalize_method(method.bytes()))));
- // 4. Set request’s method to method.
- request->set_method(MUST(ByteBuffer::copy(method.bytes())));
- }
- // 26. If init["signal"] exists, then set signal to it.
- if (init.signal.has_value())
- input_signal = *init.signal;
- // 27. Set this’s request to request.
- // NOTE: This is done at the beginning as the 'this' value Request object
- // cannot exist with a null Infrastructure::Request.
- // 28. Set this’s signal to a new AbortSignal object with this’s relevant Realm.
- auto& this_relevant_realm = HTML::relevant_realm(*request_object);
- request_object->m_signal = MUST_OR_THROW_OOM(realm.heap().allocate<DOM::AbortSignal>(this_relevant_realm, this_relevant_realm));
- // 29. If signal is not null, then make this’s signal follow signal.
- if (input_signal != nullptr)
- request_object->m_signal->follow(*input_signal);
- // 30. Set this’s headers to a new Headers object with this’s relevant Realm, whose header list is request’s header list and guard is "request".
- request_object->m_headers = MUST_OR_THROW_OOM(realm.heap().allocate<Headers>(realm, realm, request->header_list()));
- request_object->m_headers->set_guard(Headers::Guard::Request);
- // 31. If this’s request’s mode is "no-cors", then:
- if (request_object->request()->mode() == Infrastructure::Request::Mode::NoCORS) {
- // 1. If this’s request’s method is not a CORS-safelisted method, then throw a TypeError.
- if (!Infrastructure::is_cors_safelisted_method(request_object->request()->method()))
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method must be one of GET, HEAD, or POST"sv };
- // 2. Set this’s headers’s guard to "request-no-cors".
- request_object->headers()->set_guard(Headers::Guard::RequestNoCORS);
- }
- // 32. If init is not empty, then:
- if (!init.is_empty()) {
- // 1. Let headers be a copy of this’s headers and its associated header list.
- auto headers = Variant<HeadersInit, JS::NonnullGCPtr<Infrastructure::HeaderList>> { request_object->headers()->header_list() };
- // 2. If init["headers"] exists, then set headers to init["headers"].
- if (init.headers.has_value())
- headers = *init.headers;
- // 3. Empty this’s headers’s header list.
- request_object->headers()->header_list()->clear();
- // 4. If headers is a Headers object, then for each header of its header list, append header to this’s headers.
- if (auto* header_list = headers.get_pointer<JS::NonnullGCPtr<Infrastructure::HeaderList>>()) {
- for (auto& header : *header_list->ptr())
- TRY(request_object->headers()->append(TRY_OR_THROW_OOM(vm, Infrastructure::Header::from_string_pair(header.name, header.value))));
- }
- // 5. Otherwise, fill this’s headers with headers.
- else {
- TRY(request_object->headers()->fill(headers.get<HeadersInit>()));
- }
- }
- // 33. Let inputBody be input’s request’s body if input is a Request object; otherwise null.
- Optional<Infrastructure::Request::BodyType const&> input_body;
- if (input.has<JS::Handle<Request>>())
- input_body = input.get<JS::Handle<Request>>()->request()->body();
- // 34. If either init["body"] exists and is non-null or inputBody is non-null, and request’s method is `GET` or `HEAD`, then throw a TypeError.
- if (((init.body.has_value() && (*init.body).has_value()) || (input_body.has_value() && !input_body.value().has<Empty>())) && StringView { request->method() }.is_one_of("GET"sv, "HEAD"sv))
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Method must not be GET or HEAD when body is provided"sv };
- // 35. Let initBody be null.
- Optional<Infrastructure::Body> init_body;
- // 36. If init["body"] exists and is non-null, then:
- if (init.body.has_value() && (*init.body).has_value()) {
- // 1. Let bodyWithType be the result of extracting init["body"], with keepalive set to request’s keepalive.
- auto body_with_type = TRY(extract_body(realm, (*init.body).value(), request->keepalive()));
- // 2. Set initBody to bodyWithType’s body.
- init_body = move(body_with_type.body);
- // 3. Let type be bodyWithType’s type.
- auto const& type = body_with_type.type;
- // 4. If type is non-null and this’s headers’s header list does not contain `Content-Type`, then append (`Content-Type`, type) to this’s headers.
- if (type.has_value() && !request_object->headers()->header_list()->contains("Content-Type"sv.bytes()))
- TRY(request_object->headers()->append(TRY_OR_THROW_OOM(vm, Infrastructure::Header::from_string_pair("Content-Type"sv, type->span()))));
- }
- // 37. Let inputOrInitBody be initBody if it is non-null; otherwise inputBody.
- Optional<Infrastructure::Request::BodyType> input_or_init_body = init_body.has_value()
- ? Infrastructure::Request::BodyType { init_body.value() }
- : input_body;
- // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is null, then:
- // FIXME: The spec doesn't check if inputOrInitBody is a body before accessing source.
- if (input_or_init_body.has_value() && input_or_init_body->has<Infrastructure::Body>() && input_or_init_body->get<Infrastructure::Body>().source().has<Empty>()) {
- // 1. If initBody is non-null and init["duplex"] does not exist, then throw a TypeError.
- if (init_body.has_value() && !init.duplex.has_value())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Body without source requires 'duplex' value to be set"sv };
- // 2. If this’s request’s mode is neither "same-origin" nor "cors", then throw a TypeError.
- if (request_object->request()->mode() != Infrastructure::Request::Mode::SameOrigin && request_object->request()->mode() != Infrastructure::Request::Mode::CORS)
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request mode must be 'same-origin' or 'cors'"sv };
- // 3. Set this’s request’s use-CORS-preflight flag.
- request_object->request()->set_use_cors_preflight(true);
- }
- // 39. Let finalBody be inputOrInitBody.
- auto const& final_body = input_or_init_body;
- // 40. If initBody is null and inputBody is non-null, then:
- if (!init_body.has_value() && input_body.has_value()) {
- // 2. If input is unusable, then throw a TypeError.
- if (input.has<JS::Handle<Request>>() && input.get<JS::Handle<Request>>()->is_unusable())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request is unusable"sv };
- // FIXME: 2. Set finalBody to the result of creating a proxy for inputBody.
- }
- // 41. Set this’s request’s body to finalBody.
- if (final_body.has_value())
- request_object->request()->set_body(*final_body);
- return JS::NonnullGCPtr { *request_object };
- }
- // https://fetch.spec.whatwg.org/#dom-request-method
- WebIDL::ExceptionOr<String> Request::method() const
- {
- auto& vm = this->vm();
- // The method getter steps are to return this’s request’s method.
- return TRY_OR_THROW_OOM(vm, String::from_utf8(m_request->method()));
- }
- // https://fetch.spec.whatwg.org/#dom-request-url
- WebIDL::ExceptionOr<String> Request::url() const
- {
- auto& vm = this->vm();
- // The url getter steps are to return this’s request’s URL, serialized.
- return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(m_request->url().serialize()));
- }
- // https://fetch.spec.whatwg.org/#dom-request-headers
- JS::NonnullGCPtr<Headers> Request::headers() const
- {
- // The headers getter steps are to return this’s headers.
- return *m_headers;
- }
- // https://fetch.spec.whatwg.org/#dom-request-destination
- Bindings::RequestDestination Request::destination() const
- {
- // The destination getter are to return this’s request’s destination.
- return to_bindings_enum(m_request->destination());
- }
- // https://fetch.spec.whatwg.org/#dom-request-referrer
- WebIDL::ExceptionOr<String> Request::referrer() const
- {
- auto& vm = this->vm();
- return m_request->referrer().visit(
- [&](Infrastructure::Request::Referrer const& referrer) -> WebIDL::ExceptionOr<String> {
- switch (referrer) {
- // 1. If this’s request’s referrer is "no-referrer", then return the empty string.
- case Infrastructure::Request::Referrer::NoReferrer:
- return String {};
- // 2. If this’s request’s referrer is "client", then return "about:client".
- case Infrastructure::Request::Referrer::Client:
- return TRY_OR_THROW_OOM(vm, "about:client"_string);
- default:
- VERIFY_NOT_REACHED();
- }
- },
- [&](AK::URL const& url) -> WebIDL::ExceptionOr<String> {
- // 3. Return this’s request’s referrer, serialized.
- return TRY_OR_THROW_OOM(vm, String::from_deprecated_string(url.serialize()));
- });
- }
- // https://fetch.spec.whatwg.org/#dom-request-referrerpolicy
- Bindings::ReferrerPolicy Request::referrer_policy() const
- {
- // The referrerPolicy getter steps are to return this’s request’s referrer policy.
- return to_bindings_enum(m_request->referrer_policy());
- }
- // https://fetch.spec.whatwg.org/#dom-request-mode
- Bindings::RequestMode Request::mode() const
- {
- // The mode getter steps are to return this’s request’s mode.
- return to_bindings_enum(m_request->mode());
- }
- // https://fetch.spec.whatwg.org/#dom-request-credentials
- Bindings::RequestCredentials Request::credentials() const
- {
- // The credentials getter steps are to return this’s request’s credentials mode.
- return to_bindings_enum(m_request->credentials_mode());
- }
- // https://fetch.spec.whatwg.org/#dom-request-cache
- Bindings::RequestCache Request::cache() const
- {
- // The cache getter steps are to return this’s request’s cache mode.
- return to_bindings_enum(m_request->cache_mode());
- }
- // https://fetch.spec.whatwg.org/#dom-request-redirect
- Bindings::RequestRedirect Request::redirect() const
- {
- // The redirect getter steps are to return this’s request’s redirect mode.
- return to_bindings_enum(m_request->redirect_mode());
- }
- // https://fetch.spec.whatwg.org/#dom-request-integrity
- String Request::integrity() const
- {
- // The integrity getter steps are to return this’s request’s integrity metadata.
- return m_request->integrity_metadata();
- }
- // https://fetch.spec.whatwg.org/#dom-request-keepalive
- bool Request::keepalive() const
- {
- // The keepalive getter steps are to return this’s request’s keepalive.
- return m_request->keepalive();
- }
- // https://fetch.spec.whatwg.org/#dom-request-isreloadnavigation
- bool Request::is_reload_navigation() const
- {
- // The isReloadNavigation getter steps are to return true if this’s request’s reload-navigation flag is set; otherwise false.
- return m_request->reload_navigation();
- }
- // https://fetch.spec.whatwg.org/#dom-request-ishistorynavigation
- bool Request::is_history_navigation() const
- {
- // The isHistoryNavigation getter steps are to return true if this’s request’s history-navigation flag is set; otherwise false.
- return m_request->history_navigation();
- }
- // https://fetch.spec.whatwg.org/#dom-request-signal
- JS::NonnullGCPtr<DOM::AbortSignal> Request::signal() const
- {
- // The signal getter steps are to return this’s signal.
- return *m_signal;
- }
- // https://fetch.spec.whatwg.org/#dom-request-duplex
- Bindings::RequestDuplex Request::duplex() const
- {
- // The duplex getter steps are to return "half".
- return Bindings::RequestDuplex::Half;
- }
- // https://fetch.spec.whatwg.org/#dom-request-clone
- WebIDL::ExceptionOr<JS::NonnullGCPtr<Request>> Request::clone() const
- {
- auto& realm = this->realm();
- // 1. If this is unusable, then throw a TypeError.
- if (is_unusable())
- return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Request is unusable"sv };
- // 2. Let clonedRequest be the result of cloning this’s request.
- auto cloned_request = TRY(m_request->clone(realm));
- // 3. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, this’s headers’s guard, and this’s relevant Realm.
- auto cloned_request_object = TRY(Request::create(HTML::relevant_realm(*this), cloned_request, m_headers->guard()));
- // 4. Make clonedRequestObject’s signal follow this’s signal.
- cloned_request_object->m_signal->follow(*m_signal);
- // 5. Return clonedRequestObject.
- return cloned_request_object;
- }
- }
|