2022-09-25 18:33:13 +00:00
/*
2023-03-02 22:26:12 +00:00
* Copyright ( c ) 2022 - 2023 , Linus Groh < linusg @ serenityos . org >
2022-09-25 18:33:13 +00:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2023-01-07 17:14:54 +00:00
# include <LibJS/Runtime/Completion.h>
2022-09-26 00:08:29 +00:00
# include <LibWeb/Bindings/Intrinsics.h>
2022-10-14 22:41:10 +00:00
# include <LibWeb/Bindings/RequestPrototype.h>
2022-09-25 18:33:13 +00:00
# include <LibWeb/DOM/AbortSignal.h>
2024-02-11 06:48:56 +00:00
# include <LibWeb/DOMURL/DOMURL.h>
2022-09-25 18:33:13 +00:00
# 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 {
2023-11-19 18:47:52 +00:00
JS_DEFINE_ALLOCATOR ( Request ) ;
2022-10-30 01:52:07 +00:00
Request : : Request ( JS : : Realm & realm , JS : : NonnullGCPtr < Infrastructure : : Request > request )
2022-09-25 18:33:13 +00:00
: PlatformObject ( realm )
2022-10-30 01:52:07 +00:00
, m_request ( request )
2022-09-25 18:33:13 +00:00
{
}
Request : : ~ Request ( ) = default ;
2023-08-07 06:41:28 +00:00
void Request : : initialize ( JS : : Realm & realm )
2023-01-10 11:28:20 +00:00
{
2023-08-07 06:41:28 +00:00
Base : : initialize ( realm ) ;
2024-03-16 12:13:08 +00:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( Request ) ;
2023-01-10 11:28:20 +00:00
}
2022-09-25 18:33:13 +00:00
void Request : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
2022-10-30 01:52:07 +00:00
visitor . visit ( m_request ) ;
2022-09-25 18:33:13 +00:00
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
2024-04-27 14:15:01 +00:00
Optional < MimeSniff : : MimeType > Request : : mime_type_impl ( ) const
2022-09-25 18:33:13 +00:00
{
// 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
2023-08-18 17:38:13 +00:00
JS : : GCPtr < Infrastructure : : Body const > Request : : body_impl ( ) const
2022-09-25 18:33:13 +00:00
{
// 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 (
2023-08-18 17:38:13 +00:00
[ ] ( JS : : NonnullGCPtr < Infrastructure : : Body > const & b ) - > JS : : GCPtr < Infrastructure : : Body const > { return b ; } ,
[ ] ( Empty ) - > JS : : GCPtr < Infrastructure : : Body const > { return nullptr ; } ,
2022-09-25 18:33:13 +00:00
// A byte sequence will be safely extracted into a body early on in fetch.
2023-08-18 17:38:13 +00:00
[ ] ( ByteBuffer const & ) - > JS : : GCPtr < Infrastructure : : Body const > { VERIFY_NOT_REACHED ( ) ; } ) ;
2022-09-25 18:33:13 +00:00
}
// https://fetch.spec.whatwg.org/#concept-body-body
// https://fetch.spec.whatwg.org/#ref-for-concept-body-body%E2%91%A7
2023-08-18 17:38:13 +00:00
JS : : GCPtr < Infrastructure : : Body > Request : : body_impl ( )
2022-09-25 18:33:13 +00:00
{
// 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 (
2023-08-18 17:38:13 +00:00
[ ] ( JS : : NonnullGCPtr < Infrastructure : : Body > & b ) - > JS : : GCPtr < Infrastructure : : Body > { return b ; } ,
[ ] ( Empty ) - > JS : : GCPtr < Infrastructure : : Body > { return { } ; } ,
2022-09-25 18:33:13 +00:00
// A byte sequence will be safely extracted into a body early on in fetch.
2023-08-18 17:38:13 +00:00
[ ] ( ByteBuffer & ) - > JS : : GCPtr < Infrastructure : : Body > { VERIFY_NOT_REACHED ( ) ; } ) ;
2022-09-25 18:33:13 +00:00
}
// https://fetch.spec.whatwg.org/#request-create
2024-03-26 07:45:11 +00:00
JS : : NonnullGCPtr < Request > Request : : create ( JS : : Realm & realm , JS : : NonnullGCPtr < Infrastructure : : Request > request , Headers : : Guard guard , JS : : NonnullGCPtr < DOM : : AbortSignal > signal )
2022-09-25 18:33:13 +00:00
{
// 1. Let requestObject be a new Request object with realm.
// 2. Set requestObject’ s request to request.
2023-08-13 11:05:26 +00:00
auto request_object = realm . heap ( ) . allocate < Request > ( realm , realm , request ) ;
2022-09-25 18:33:13 +00:00
// 3. Set requestObject’ s headers to a new Headers object with realm, whose headers list is request’ s headers list and guard is guard.
2023-08-13 11:05:26 +00:00
request_object - > m_headers = realm . heap ( ) . allocate < Headers > ( realm , realm , request - > header_list ( ) ) ;
2022-09-25 18:33:13 +00:00
request_object - > m_headers - > set_guard ( guard ) ;
2024-03-26 07:45:11 +00:00
// 4. Set requestObject’ s signal to signal.
request_object - > m_signal = signal ;
2022-09-25 18:33:13 +00:00
// 5. Return requestObject.
2022-12-14 17:40:33 +00:00
return request_object ;
2022-09-25 18:33:13 +00:00
}
// https://fetch.spec.whatwg.org/#dom-request
2022-09-26 00:08:29 +00:00
WebIDL : : ExceptionOr < JS : : NonnullGCPtr < Request > > Request : : construct_impl ( JS : : Realm & realm , RequestInfo const & input , RequestInit const & init )
2022-09-25 18:33:13 +00:00
{
2022-10-30 01:52:07 +00:00
auto & vm = realm . vm ( ) ;
2022-09-25 18:33:13 +00:00
// Referred to as 'this' in the spec.
2023-08-13 11:05:26 +00:00
auto request_object = realm . heap ( ) . allocate < Request > ( realm , realm , Infrastructure : : Request : : create ( vm ) ) ;
2022-09-25 18:33:13 +00:00
// 1. Let request be null.
2022-10-30 01:52:07 +00:00
JS : : GCPtr < Infrastructure : : Request > input_request ;
2022-09-25 18:33:13 +00:00
// 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.
2023-02-25 17:44:51 +00:00
DOM : : AbortSignal * input_signal = nullptr ;
2022-09-25 18:33:13 +00:00
// 5. If input is a string, then:
2023-03-02 22:26:12 +00:00
if ( input . has < String > ( ) ) {
2022-09-25 18:33:13 +00:00
// 1. Let parsedURL be the result of parsing input with baseURL.
2024-02-11 06:48:56 +00:00
auto parsed_url = DOMURL : : parse ( input . get < String > ( ) , base_url ) ;
2022-09-25 18:33:13 +00:00
// 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.
2022-10-30 01:52:07 +00:00
input_request = Infrastructure : : Request : : create ( vm ) ;
2022-10-04 22:45:47 +00:00
input_request - > set_url ( move ( parsed_url ) ) ;
2022-09-25 18:33:13 +00:00
// 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.
2022-10-04 22:45:47 +00:00
input_request = input . get < JS : : Handle < Request > > ( ) - > request ( ) ;
2022-09-25 18:33:13 +00:00
// 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.
2023-02-26 23:09:02 +00:00
if ( input_request - > window ( ) . has < JS : : GCPtr < HTML : : EnvironmentSettingsObject > > ( ) ) {
auto eso = input_request - > window ( ) . get < JS : : GCPtr < HTML : : EnvironmentSettingsObject > > ( ) ;
2022-09-25 18:33:13 +00:00
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.
2022-10-04 22:45:47 +00:00
auto request = request_object - > request ( ) ;
2022-09-25 18:33:13 +00:00
// URL
// request’ s URL.
2022-10-04 22:45:47 +00:00
request - > set_url ( input_request - > url ( ) ) ;
2022-09-25 18:33:13 +00:00
// method
// request’ s method.
2024-04-27 14:31:50 +00:00
request - > set_method ( MUST ( ByteBuffer : : copy ( input_request - > method ( ) ) ) ) ;
2022-09-25 18:33:13 +00:00
// header list
// A copy of request’ s header list.
2022-10-30 01:52:07 +00:00
auto header_list_copy = Infrastructure : : HeaderList : : create ( vm ) ;
2022-11-04 21:20:46 +00:00
for ( auto & header : * input_request - > header_list ( ) )
2024-04-26 17:24:20 +00:00
header_list_copy - > append ( header ) ;
2022-10-30 01:52:07 +00:00
request - > set_header_list ( header_list_copy ) ;
2022-09-25 18:33:13 +00:00
// unsafe-request flag
// Set.
2022-10-04 22:45:47 +00:00
request - > set_unsafe_request ( true ) ;
2022-09-25 18:33:13 +00:00
// client
// This’ s relevant settings object.
2022-10-04 22:45:47 +00:00
request - > set_client ( & HTML : : relevant_settings_object ( * request_object ) ) ;
2022-09-25 18:33:13 +00:00
// window
// window.
2022-10-04 22:45:47 +00:00
request - > set_window ( window ) ;
2022-09-25 18:33:13 +00:00
// priority
// request’ s priority.
2022-10-04 22:45:47 +00:00
request - > set_priority ( input_request - > priority ( ) ) ;
2022-09-25 18:33:13 +00:00
// 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.
2022-10-04 22:45:47 +00:00
request - > set_origin ( input_request - > origin ( ) ) ;
2022-09-25 18:33:13 +00:00
// referrer
// request’ s referrer.
2022-10-04 22:45:47 +00:00
request - > set_referrer ( input_request - > referrer ( ) ) ;
2022-09-25 18:33:13 +00:00
// referrer policy
// request’ s referrer policy.
2022-10-04 22:45:47 +00:00
request - > set_referrer_policy ( input_request - > referrer_policy ( ) ) ;
2022-09-25 18:33:13 +00:00
// mode
// request’ s mode.
2022-10-04 22:45:47 +00:00
request - > set_mode ( input_request - > mode ( ) ) ;
2022-09-25 18:33:13 +00:00
// credentials mode
// request’ s credentials mode.
2022-10-04 22:45:47 +00:00
request - > set_credentials_mode ( input_request - > credentials_mode ( ) ) ;
2022-09-25 18:33:13 +00:00
// cache mode
// request’ s cache mode.
2022-10-04 22:45:47 +00:00
request - > set_cache_mode ( input_request - > cache_mode ( ) ) ;
2022-09-25 18:33:13 +00:00
// redirect mode
// request’ s redirect mode.
2022-10-04 22:45:47 +00:00
request - > set_redirect_mode ( input_request - > redirect_mode ( ) ) ;
2022-09-25 18:33:13 +00:00
// integrity metadata
// request’ s integrity metadata.
2022-10-04 22:45:47 +00:00
request - > set_integrity_metadata ( input_request - > integrity_metadata ( ) ) ;
2022-09-25 18:33:13 +00:00
// keepalive
// request’ s keepalive.
2022-10-04 22:45:47 +00:00
request - > set_keepalive ( input_request - > keepalive ( ) ) ;
2022-09-25 18:33:13 +00:00
// reload-navigation flag
// request’ s reload-navigation flag.
2022-10-04 22:45:47 +00:00
request - > set_reload_navigation ( input_request - > reload_navigation ( ) ) ;
2022-09-25 18:33:13 +00:00
// history-navigation flag
// request’ s history-navigation flag.
2022-10-04 22:45:47 +00:00
request - > set_history_navigation ( input_request - > history_navigation ( ) ) ;
2022-09-25 18:33:13 +00:00
// URL list
// A clone of request’ s URL list.
2022-10-04 22:45:47 +00:00
request - > set_url_list ( input_request - > url_list ( ) ) ;
2022-09-25 18:33:13 +00:00
// initiator type
// "fetch".
2022-10-04 22:45:47 +00:00
request - > set_initiator_type ( Infrastructure : : Request : : InitiatorType : : Fetch ) ;
2022-09-25 18:33:13 +00:00
// 13. If init is not empty, then:
if ( ! init . is_empty ( ) ) {
// 1. If request’ s mode is "navigate", then set it to "same-origin".
2022-10-04 22:45:47 +00:00
if ( request - > mode ( ) = = Infrastructure : : Request : : Mode : : Navigate )
request - > set_mode ( Infrastructure : : Request : : Mode : : SameOrigin ) ;
2022-09-25 18:33:13 +00:00
// 2. Unset request’ s reload-navigation flag.
2022-10-04 22:45:47 +00:00
request - > set_reload_navigation ( false ) ;
2022-09-25 18:33:13 +00:00
// 3. Unset request’ s history-navigation flag.
2022-10-04 22:45:47 +00:00
request - > set_history_navigation ( false ) ;
2022-09-25 18:33:13 +00:00
// 4. Set request’ s origin to "client".
2022-10-04 22:45:47 +00:00
request - > set_origin ( Infrastructure : : Request : : Origin : : Client ) ;
2022-09-25 18:33:13 +00:00
// 5. Set request’ s referrer to "client".
2022-10-04 22:45:47 +00:00
request - > set_referrer ( Infrastructure : : Request : : Referrer : : Client ) ;
2022-09-25 18:33:13 +00:00
// 6. Set request’ s referrer policy to the empty string.
2022-10-04 22:45:47 +00:00
request - > set_referrer_policy ( { } ) ;
2022-09-25 18:33:13 +00:00
// 7. Set request’ s URL to request’ s current URL.
2022-10-04 22:45:47 +00:00
request - > set_url ( request - > current_url ( ) ) ;
2022-09-25 18:33:13 +00:00
// 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 ( ) ) {
2022-10-04 22:45:47 +00:00
request - > set_referrer ( Infrastructure : : Request : : Referrer : : NoReferrer ) ;
2022-09-25 18:33:13 +00:00
}
// 3. Otherwise:
else {
// 1. Let parsedReferrer be the result of parsing referrer with baseURL.
2024-02-11 06:48:56 +00:00
auto parsed_referrer = DOMURL : : parse ( referrer , base_url ) ;
2022-09-25 18:33:13 +00:00
// 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".
2024-10-05 04:03:51 +00:00
auto parsed_referrer_origin = parsed_referrer . origin ( ) ;
2024-08-05 03:14:00 +00:00
if ( ( parsed_referrer . scheme ( ) = = " about " sv & & parsed_referrer . paths ( ) . size ( ) = = 1 & & parsed_referrer . paths ( ) [ 0 ] = = " client " sv )
| | ! parsed_referrer_origin . is_same_origin ( origin ) ) {
2022-10-04 22:45:47 +00:00
request - > set_referrer ( Infrastructure : : Request : : Referrer : : Client ) ;
2022-09-25 18:33:13 +00:00
}
// 4. Otherwise, set request’ s referrer to parsedReferrer.
else {
2022-10-04 22:45:47 +00:00
request - > set_referrer ( move ( parsed_referrer ) ) ;
2022-09-25 18:33:13 +00:00
}
}
}
// 15. If init["referrerPolicy"] exists, then set request’ s referrer policy to it.
if ( init . referrer_policy . has_value ( ) )
2022-10-04 22:45:47 +00:00
request - > set_referrer_policy ( from_bindings_enum ( * init . referrer_policy ) ) ;
2022-09-25 18:33:13 +00:00
// 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 ( ) )
2022-10-04 22:45:47 +00:00
request - > set_mode ( * mode ) ;
2022-09-25 18:33:13 +00:00
// 19. If init["credentials"] exists, then set request’ s credentials mode to it.
if ( init . credentials . has_value ( ) )
2022-10-04 22:45:47 +00:00
request - > set_credentials_mode ( from_bindings_enum ( * init . credentials ) ) ;
2022-09-25 18:33:13 +00:00
// 20. If init["cache"] exists, then set request’ s cache mode to it.
if ( init . cache . has_value ( ) )
2022-10-04 22:45:47 +00:00
request - > set_cache_mode ( from_bindings_enum ( * init . cache ) ) ;
2022-09-25 18:33:13 +00:00
// 21. If request’ s cache mode is "only-if-cached" and request’ s mode is not "same-origin", then throw a TypeError.
2022-10-04 22:45:47 +00:00
if ( request - > cache_mode ( ) = = Infrastructure : : Request : : CacheMode : : OnlyIfCached & & request - > mode ( ) ! = Infrastructure : : Request : : Mode : : SameOrigin )
2022-09-25 18:33:13 +00:00
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 ( ) )
2022-10-04 22:45:47 +00:00
request - > set_redirect_mode ( from_bindings_enum ( * init . redirect ) ) ;
2022-09-25 18:33:13 +00:00
// 23. If init["integrity"] exists, then set request’ s integrity metadata to it.
if ( init . integrity . has_value ( ) )
2023-03-02 23:26:35 +00:00
request - > set_integrity_metadata ( * init . integrity ) ;
2022-09-25 18:33:13 +00:00
// 24. If init["keepalive"] exists, then set request’ s keepalive to it.
if ( init . keepalive . has_value ( ) )
2022-10-04 22:45:47 +00:00
request - > set_keepalive ( * init . keepalive ) ;
2022-09-25 18:33:13 +00:00
// 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.
2024-04-27 14:31:50 +00:00
method = MUST ( String : : from_utf8 ( Infrastructure : : normalize_method ( method . bytes ( ) ) ) ) ;
2022-09-25 18:33:13 +00:00
// 4. Set request’ s method to method.
2022-10-04 22:45:47 +00:00
request - > set_method ( MUST ( ByteBuffer : : copy ( method . bytes ( ) ) ) ) ;
2022-09-25 18:33:13 +00:00
}
// 26. If init["signal"] exists, then set signal to it.
if ( init . signal . has_value ( ) )
input_signal = * init . signal ;
2024-05-03 23:17:24 +00:00
// 27. If init["priority"] exists, then:
if ( init . priority . has_value ( ) )
request - > set_priority ( from_bindings_enum ( * init . priority ) ) ;
2024-03-26 07:45:11 +00:00
// 28. Set this’ s request to request.
2022-09-25 18:33:13 +00:00
// NOTE: This is done at the beginning as the 'this' value Request object
// cannot exist with a null Infrastructure::Request.
2024-03-26 07:45:11 +00:00
// 29. Let signals be « signal » if signal is non-null; otherwise « ».
2022-09-26 00:08:29 +00:00
auto & this_relevant_realm = HTML : : relevant_realm ( * request_object ) ;
2024-03-26 07:45:11 +00:00
Vector < JS : : Handle < DOM : : AbortSignal > > signals ;
2022-10-26 17:17:47 +00:00
if ( input_signal ! = nullptr )
2024-03-26 07:45:11 +00:00
signals . append ( * input_signal ) ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 30. Set this’ s signal to the result of creating a dependent abort signal from signals, using AbortSignal and this’ s relevant realm.
request_object - > m_signal = TRY ( DOM : : AbortSignal : : create_dependent_abort_signal ( this_relevant_realm , signals ) ) ;
// 31. 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".
2023-08-13 11:05:26 +00:00
request_object - > m_headers = realm . heap ( ) . allocate < Headers > ( realm , realm , request - > header_list ( ) ) ;
2022-09-25 18:33:13 +00:00
request_object - > m_headers - > set_guard ( Headers : : Guard : : Request ) ;
2024-03-26 07:45:11 +00:00
// 32. If this’ s request’ s mode is "no-cors", then:
2022-10-04 22:45:47 +00:00
if ( request_object - > request ( ) - > mode ( ) = = Infrastructure : : Request : : Mode : : NoCORS ) {
2022-09-25 18:33:13 +00:00
// 1. If this’ s request’ s method is not a CORS-safelisted method, then throw a TypeError.
2022-10-04 22:45:47 +00:00
if ( ! Infrastructure : : is_cors_safelisted_method ( request_object - > request ( ) - > method ( ) ) )
2022-09-25 18:33:13 +00:00
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 ) ;
}
2024-03-26 07:45:11 +00:00
// 33. If init is not empty, then:
2022-09-25 18:33:13 +00:00
if ( ! init . is_empty ( ) ) {
// 1. Let headers be a copy of this’ s headers and its associated header list.
2022-10-30 01:52:07 +00:00
auto headers = Variant < HeadersInit , JS : : NonnullGCPtr < Infrastructure : : HeaderList > > { request_object - > headers ( ) - > header_list ( ) } ;
2022-09-25 18:33:13 +00:00
// 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 ( ) ;
2022-12-07 18:29:17 +00:00
// 4. If headers is a Headers object, then for each header of its header list, append header to this’ s headers.
2022-10-30 01:52:07 +00:00
if ( auto * header_list = headers . get_pointer < JS : : NonnullGCPtr < Infrastructure : : HeaderList > > ( ) ) {
for ( auto & header : * header_list - > ptr ( ) )
2024-04-26 17:24:20 +00:00
TRY ( request_object - > headers ( ) - > append ( Infrastructure : : Header : : from_string_pair ( header . name , header . value ) ) ) ;
2022-09-25 18:33:13 +00:00
}
// 5. Otherwise, fill this’ s headers with headers.
else {
2022-10-30 17:50:04 +00:00
TRY ( request_object - > headers ( ) - > fill ( headers . get < HeadersInit > ( ) ) ) ;
2022-09-25 18:33:13 +00:00
}
}
2024-03-26 07:45:11 +00:00
// 34. Let inputBody be input’ s request’ s body if input is a Request object; otherwise null.
2022-10-26 09:32:53 +00:00
Optional < Infrastructure : : Request : : BodyType const & > input_body ;
if ( input . has < JS : : Handle < Request > > ( ) )
input_body = input . get < JS : : Handle < Request > > ( ) - > request ( ) - > body ( ) ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 35. 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.
2022-10-26 09:32:53 +00:00
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 ) )
2022-09-25 18:33:13 +00:00
return WebIDL : : SimpleException { WebIDL : : SimpleExceptionType : : TypeError , " Method must not be GET or HEAD when body is provided " sv } ;
2024-03-26 07:45:11 +00:00
// 36. Let initBody be null.
2023-08-18 17:38:13 +00:00
JS : : GCPtr < Infrastructure : : Body > init_body ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 37. If init["body"] exists and is non-null, then:
2022-09-25 18:33:13 +00:00
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.
2022-10-04 22:45:47 +00:00
auto body_with_type = TRY ( extract_body ( realm , ( * init . body ) . value ( ) , request - > keepalive ( ) ) ) ;
2022-09-25 18:33:13 +00:00
// 2. Set initBody to bodyWithType’ s body.
2023-08-18 17:38:13 +00:00
init_body = body_with_type . body ;
2022-09-25 18:33:13 +00:00
// 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 ( ) ) )
2024-04-26 17:24:20 +00:00
TRY ( request_object - > headers ( ) - > append ( Infrastructure : : Header : : from_string_pair ( " Content-Type " sv , type - > span ( ) ) ) ) ;
2022-09-25 18:33:13 +00:00
}
2024-03-26 07:45:11 +00:00
// 38. Let inputOrInitBody be initBody if it is non-null; otherwise inputBody.
2023-08-18 17:38:13 +00:00
Optional < Infrastructure : : Request : : BodyType > input_or_init_body = init_body
? Infrastructure : : Request : : BodyType { * init_body }
2022-10-26 09:32:53 +00:00
: input_body ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 39. If inputOrInitBody is non-null and inputOrInitBody’ s source is null, then:
2022-10-26 09:32:53 +00:00
// FIXME: The spec doesn't check if inputOrInitBody is a body before accessing source.
2023-08-18 17:38:13 +00:00
if ( input_or_init_body . has_value ( ) & & input_or_init_body - > has < JS : : NonnullGCPtr < Infrastructure : : Body > > ( ) & & input_or_init_body - > get < JS : : NonnullGCPtr < Infrastructure : : Body > > ( ) - > source ( ) . has < Empty > ( ) ) {
2022-09-25 18:33:13 +00:00
// 1. If initBody is non-null and init["duplex"] does not exist, then throw a TypeError.
2023-08-18 17:38:13 +00:00
if ( init_body & & ! init . duplex . has_value ( ) )
2022-09-25 18:33:13 +00:00
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.
2022-10-04 22:45:47 +00:00
if ( request_object - > request ( ) - > mode ( ) ! = Infrastructure : : Request : : Mode : : SameOrigin & & request_object - > request ( ) - > mode ( ) ! = Infrastructure : : Request : : Mode : : CORS )
2022-09-25 18:33:13 +00:00
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.
2022-10-04 22:45:47 +00:00
request_object - > request ( ) - > set_use_cors_preflight ( true ) ;
2022-09-25 18:33:13 +00:00
}
2024-03-26 07:45:11 +00:00
// 40. Let finalBody be inputOrInitBody.
2022-09-25 18:33:13 +00:00
auto const & final_body = input_or_init_body ;
2024-03-26 07:45:11 +00:00
// 41. If initBody is null and inputBody is non-null, then:
2023-08-18 17:38:13 +00:00
if ( ! init_body & & input_body . has_value ( ) ) {
2022-09-25 18:33:13 +00:00
// 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.
}
2024-03-26 07:45:11 +00:00
// 42. Set this’ s request’ s body to finalBody.
2022-09-25 18:33:13 +00:00
if ( final_body . has_value ( ) )
2022-10-04 22:45:47 +00:00
request_object - > request ( ) - > set_body ( * final_body ) ;
2022-09-25 18:33:13 +00:00
return JS : : NonnullGCPtr { * request_object } ;
}
// https://fetch.spec.whatwg.org/#dom-request-method
2024-04-27 14:31:50 +00:00
String Request : : method ( ) const
2022-09-25 18:33:13 +00:00
{
// The method getter steps are to return this’ s request’ s method.
2024-04-27 14:31:50 +00:00
return MUST ( String : : from_utf8 ( m_request - > method ( ) ) ) ;
2022-09-25 18:33:13 +00:00
}
// https://fetch.spec.whatwg.org/#dom-request-url
2024-04-27 14:31:50 +00:00
String Request : : url ( ) const
2022-09-25 18:33:13 +00:00
{
// The url getter steps are to return this’ s request’ s URL, serialized.
2024-04-27 14:31:50 +00:00
return MUST ( String : : from_byte_string ( m_request - > url ( ) . serialize ( ) ) ) ;
2022-09-25 18:33:13 +00:00
}
// 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
2024-04-27 14:31:50 +00:00
String Request : : referrer ( ) const
2022-09-25 18:33:13 +00:00
{
return m_request - > referrer ( ) . visit (
2024-04-27 14:31:50 +00:00
[ & ] ( Infrastructure : : Request : : Referrer const & referrer ) {
2022-09-25 18:33:13 +00:00
switch ( referrer ) {
// 1. If this’ s request’ s referrer is "no-referrer", then return the empty string.
case Infrastructure : : Request : : Referrer : : NoReferrer :
2023-03-02 22:26:12 +00:00
return String { } ;
2022-09-25 18:33:13 +00:00
// 2. If this’ s request’ s referrer is "client", then return "about:client".
case Infrastructure : : Request : : Referrer : : Client :
2023-08-07 09:12:38 +00:00
return " about:client " _string ;
2022-09-25 18:33:13 +00:00
default :
VERIFY_NOT_REACHED ( ) ;
}
} ,
2024-04-27 14:31:50 +00:00
[ & ] ( URL : : URL const & url ) {
2022-09-25 18:33:13 +00:00
// 3. Return this’ s request’ s referrer, serialized.
2024-04-27 14:31:50 +00:00
return MUST ( String : : from_byte_string ( url . serialize ( ) ) ) ;
2022-09-25 18:33:13 +00:00
} ) ;
}
// 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
2023-03-02 23:26:35 +00:00
String Request : : integrity ( ) const
2022-09-25 18:33:13 +00:00
{
// The integrity getter steps are to return this’ s request’ s integrity metadata.
2023-03-02 23:26:35 +00:00
return m_request - > integrity_metadata ( ) ;
2022-09-25 18:33:13 +00:00
}
// 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 ;
}
2022-10-14 22:41:10 +00:00
// 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 ;
}
2022-09-25 18:33:13 +00:00
// https://fetch.spec.whatwg.org/#dom-request-clone
WebIDL : : ExceptionOr < JS : : NonnullGCPtr < Request > > Request : : clone ( ) const
{
2023-02-28 17:45:49 +00:00
auto & realm = this - > realm ( ) ;
2022-10-30 01:52:07 +00:00
2022-09-25 18:33:13 +00:00
// 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.
2023-08-13 11:05:26 +00:00
auto cloned_request = m_request - > clone ( realm ) ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 3. Assert: this’ s signal is non-null.
VERIFY ( m_signal ) ;
// 4. Let clonedSignal be the result of creating a dependent abort signal from « this’ s signal », using AbortSignal and this’ s relevant realm.
auto & relevant_realm = HTML : : relevant_realm ( * this ) ;
auto cloned_signal = TRY ( DOM : : AbortSignal : : create_dependent_abort_signal ( relevant_realm , { m_signal } ) ) ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 5. Let clonedRequestObject be the result of creating a Request object, given clonedRequest, this’ s headers’ s guard, clonedSignal and this’ s relevant realm.
auto cloned_request_object = Request : : create ( relevant_realm , cloned_request , m_headers - > guard ( ) , cloned_signal ) ;
2022-09-25 18:33:13 +00:00
2024-03-26 07:45:11 +00:00
// 6. Return clonedRequestObject.
2022-09-25 18:33:13 +00:00
return cloned_request_object ;
}
}