Requests.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /*
  2. * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
  3. * Copyright (c) 2023, networkException <networkexception@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/ByteBuffer.h>
  9. #include <AK/Error.h>
  10. #include <AK/Forward.h>
  11. #include <AK/Optional.h>
  12. #include <AK/String.h>
  13. #include <AK/Variant.h>
  14. #include <AK/Vector.h>
  15. #include <LibJS/Forward.h>
  16. #include <LibJS/Heap/Cell.h>
  17. #include <LibJS/Heap/GCPtr.h>
  18. #include <LibURL/URL.h>
  19. #include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
  20. #include <LibWeb/Fetch/Infrastructure/HTTP/Headers.h>
  21. #include <LibWeb/HTML/Origin.h>
  22. #include <LibWeb/HTML/PolicyContainers.h>
  23. #include <LibWeb/HTML/Scripting/Environments.h>
  24. namespace Web::Fetch::Infrastructure {
  25. // https://fetch.spec.whatwg.org/#concept-request
  26. class Request final : public JS::Cell {
  27. JS_CELL(Request, JS::Cell);
  28. JS_DECLARE_ALLOCATOR(Request);
  29. public:
  30. enum class CacheMode {
  31. Default,
  32. NoStore,
  33. Reload,
  34. NoCache,
  35. ForceCache,
  36. OnlyIfCached,
  37. };
  38. enum class CredentialsMode {
  39. Omit,
  40. SameOrigin,
  41. Include,
  42. };
  43. enum class Destination {
  44. Audio,
  45. AudioWorklet,
  46. Document,
  47. Embed,
  48. Font,
  49. Frame,
  50. IFrame,
  51. Image,
  52. JSON,
  53. Manifest,
  54. Object,
  55. PaintWorklet,
  56. Report,
  57. Script,
  58. ServiceWorker,
  59. SharedWorker,
  60. Style,
  61. Track,
  62. Video,
  63. WebIdentity,
  64. Worker,
  65. XSLT,
  66. };
  67. enum class Initiator {
  68. Download,
  69. ImageSet,
  70. Manifest,
  71. Prefetch,
  72. Prerender,
  73. XSLT,
  74. };
  75. enum class InitiatorType {
  76. Audio,
  77. Beacon,
  78. Body,
  79. CSS,
  80. EarlyHint,
  81. Embed,
  82. Fetch,
  83. Font,
  84. Frame,
  85. IFrame,
  86. Image,
  87. IMG,
  88. Input,
  89. Link,
  90. Object,
  91. Ping,
  92. Script,
  93. Track,
  94. Video,
  95. XMLHttpRequest,
  96. Other,
  97. };
  98. enum class Mode {
  99. SameOrigin,
  100. CORS,
  101. NoCORS,
  102. Navigate,
  103. WebSocket,
  104. };
  105. enum class Origin {
  106. Client,
  107. };
  108. enum class ParserMetadata {
  109. ParserInserted,
  110. NotParserInserted,
  111. };
  112. enum class PolicyContainer {
  113. Client,
  114. };
  115. enum class RedirectMode {
  116. Follow,
  117. Error,
  118. Manual,
  119. };
  120. enum class Referrer {
  121. NoReferrer,
  122. Client,
  123. };
  124. enum class ResponseTainting {
  125. Basic,
  126. CORS,
  127. Opaque,
  128. };
  129. enum class ServiceWorkersMode {
  130. All,
  131. None,
  132. };
  133. enum class Window {
  134. NoWindow,
  135. Client,
  136. };
  137. enum class Priority {
  138. High,
  139. Low,
  140. Auto
  141. };
  142. // AD-HOC: Some web features need to receive data as it arrives, rather than when the response is fully complete
  143. // or when enough data has been buffered. Use this buffer policy to inform fetch of that requirement.
  144. enum class BufferPolicy {
  145. BufferResponse,
  146. DoNotBufferResponse,
  147. };
  148. // Members are implementation-defined
  149. struct InternalPriority { };
  150. using BodyType = Variant<Empty, ByteBuffer, JS::NonnullGCPtr<Body>>;
  151. using OriginType = Variant<Origin, HTML::Origin>;
  152. using PolicyContainerType = Variant<PolicyContainer, HTML::PolicyContainer>;
  153. using ReferrerType = Variant<Referrer, URL::URL>;
  154. using ReservedClientType = JS::GCPtr<HTML::Environment>;
  155. using WindowType = Variant<Window, JS::GCPtr<HTML::EnvironmentSettingsObject>>;
  156. [[nodiscard]] static JS::NonnullGCPtr<Request> create(JS::VM&);
  157. [[nodiscard]] ReadonlyBytes method() const { return m_method; }
  158. void set_method(ByteBuffer method) { m_method = move(method); }
  159. [[nodiscard]] bool local_urls_only() const { return m_local_urls_only; }
  160. void set_local_urls_only(bool local_urls_only) { m_local_urls_only = local_urls_only; }
  161. [[nodiscard]] JS::NonnullGCPtr<HeaderList> header_list() const { return m_header_list; }
  162. void set_header_list(JS::NonnullGCPtr<HeaderList> header_list) { m_header_list = header_list; }
  163. [[nodiscard]] bool unsafe_request() const { return m_unsafe_request; }
  164. void set_unsafe_request(bool unsafe_request) { m_unsafe_request = unsafe_request; }
  165. [[nodiscard]] BodyType const& body() const { return m_body; }
  166. [[nodiscard]] BodyType& body() { return m_body; }
  167. void set_body(BodyType body) { m_body = move(body); }
  168. [[nodiscard]] JS::GCPtr<HTML::EnvironmentSettingsObject const> client() const { return m_client; }
  169. [[nodiscard]] JS::GCPtr<HTML::EnvironmentSettingsObject> client() { return m_client; }
  170. void set_client(HTML::EnvironmentSettingsObject* client) { m_client = client; }
  171. [[nodiscard]] ReservedClientType const& reserved_client() const { return m_reserved_client; }
  172. [[nodiscard]] ReservedClientType& reserved_client() { return m_reserved_client; }
  173. void set_reserved_client(ReservedClientType reserved_client) { m_reserved_client = move(reserved_client); }
  174. [[nodiscard]] String const& replaces_client_id() const { return m_replaces_client_id; }
  175. void set_replaces_client_id(String replaces_client_id) { m_replaces_client_id = move(replaces_client_id); }
  176. [[nodiscard]] WindowType const& window() const { return m_window; }
  177. void set_window(WindowType window) { m_window = move(window); }
  178. [[nodiscard]] bool keepalive() const { return m_keepalive; }
  179. void set_keepalive(bool keepalive) { m_keepalive = keepalive; }
  180. [[nodiscard]] Optional<InitiatorType> const& initiator_type() const { return m_initiator_type; }
  181. void set_initiator_type(Optional<InitiatorType> initiator_type) { m_initiator_type = move(initiator_type); }
  182. [[nodiscard]] ServiceWorkersMode service_workers_mode() const { return m_service_workers_mode; }
  183. void set_service_workers_mode(ServiceWorkersMode service_workers_mode) { m_service_workers_mode = service_workers_mode; }
  184. [[nodiscard]] Optional<Initiator> const& initiator() const { return m_initiator; }
  185. void set_initiator(Optional<Initiator> initiator) { m_initiator = move(initiator); }
  186. [[nodiscard]] Optional<Destination> const& destination() const { return m_destination; }
  187. void set_destination(Optional<Destination> destination) { m_destination = move(destination); }
  188. [[nodiscard]] Priority const& priority() const { return m_priority; }
  189. void set_priority(Priority priority) { m_priority = priority; }
  190. [[nodiscard]] OriginType const& origin() const { return m_origin; }
  191. void set_origin(OriginType origin) { m_origin = move(origin); }
  192. [[nodiscard]] PolicyContainerType const& policy_container() const { return m_policy_container; }
  193. void set_policy_container(PolicyContainerType policy_container) { m_policy_container = move(policy_container); }
  194. [[nodiscard]] Mode mode() const { return m_mode; }
  195. void set_mode(Mode mode) { m_mode = mode; }
  196. [[nodiscard]] bool use_cors_preflight() const { return m_use_cors_preflight; }
  197. void set_use_cors_preflight(bool use_cors_preflight) { m_use_cors_preflight = use_cors_preflight; }
  198. [[nodiscard]] CredentialsMode credentials_mode() const { return m_credentials_mode; }
  199. void set_credentials_mode(CredentialsMode credentials_mode) { m_credentials_mode = credentials_mode; }
  200. [[nodiscard]] bool use_url_credentials() const { return m_use_url_credentials; }
  201. void set_use_url_credentials(bool use_url_credentials) { m_use_url_credentials = use_url_credentials; }
  202. [[nodiscard]] CacheMode cache_mode() const { return m_cache_mode; }
  203. void set_cache_mode(CacheMode cache_mode) { m_cache_mode = cache_mode; }
  204. [[nodiscard]] RedirectMode redirect_mode() const { return m_redirect_mode; }
  205. void set_redirect_mode(RedirectMode redirect_mode) { m_redirect_mode = redirect_mode; }
  206. [[nodiscard]] String const& integrity_metadata() const { return m_integrity_metadata; }
  207. void set_integrity_metadata(String integrity_metadata) { m_integrity_metadata = move(integrity_metadata); }
  208. [[nodiscard]] String const& cryptographic_nonce_metadata() const { return m_cryptographic_nonce_metadata; }
  209. void set_cryptographic_nonce_metadata(String cryptographic_nonce_metadata) { m_cryptographic_nonce_metadata = move(cryptographic_nonce_metadata); }
  210. [[nodiscard]] Optional<ParserMetadata> const& parser_metadata() const { return m_parser_metadata; }
  211. void set_parser_metadata(Optional<ParserMetadata> parser_metadata) { m_parser_metadata = move(parser_metadata); }
  212. [[nodiscard]] bool reload_navigation() const { return m_reload_navigation; }
  213. void set_reload_navigation(bool reload_navigation) { m_reload_navigation = reload_navigation; }
  214. [[nodiscard]] bool history_navigation() const { return m_history_navigation; }
  215. void set_history_navigation(bool history_navigation) { m_history_navigation = history_navigation; }
  216. [[nodiscard]] bool user_activation() const { return m_user_activation; }
  217. void set_user_activation(bool user_activation) { m_user_activation = user_activation; }
  218. [[nodiscard]] bool render_blocking() const { return m_render_blocking; }
  219. void set_render_blocking(bool render_blocking) { m_render_blocking = render_blocking; }
  220. [[nodiscard]] Vector<URL::URL> const& url_list() const { return m_url_list; }
  221. [[nodiscard]] Vector<URL::URL>& url_list() { return m_url_list; }
  222. void set_url_list(Vector<URL::URL> url_list) { m_url_list = move(url_list); }
  223. [[nodiscard]] u8 redirect_count() const { return m_redirect_count; }
  224. void set_redirect_count(u8 redirect_count) { m_redirect_count = redirect_count; }
  225. [[nodiscard]] ReferrerType const& referrer() const { return m_referrer; }
  226. void set_referrer(ReferrerType referrer) { m_referrer = move(referrer); }
  227. [[nodiscard]] ReferrerPolicy::ReferrerPolicy const& referrer_policy() const { return m_referrer_policy; }
  228. void set_referrer_policy(ReferrerPolicy::ReferrerPolicy referrer_policy) { m_referrer_policy = move(referrer_policy); }
  229. [[nodiscard]] ResponseTainting response_tainting() const { return m_response_tainting; }
  230. void set_response_tainting(ResponseTainting response_tainting) { m_response_tainting = response_tainting; }
  231. [[nodiscard]] bool prevent_no_cache_cache_control_header_modification() const { return m_prevent_no_cache_cache_control_header_modification; }
  232. void set_prevent_no_cache_cache_control_header_modification(bool prevent_no_cache_cache_control_header_modification) { m_prevent_no_cache_cache_control_header_modification = prevent_no_cache_cache_control_header_modification; }
  233. [[nodiscard]] bool done() const { return m_done; }
  234. void set_done(bool done) { m_done = done; }
  235. [[nodiscard]] bool timing_allow_failed() const { return m_timing_allow_failed; }
  236. void set_timing_allow_failed(bool timing_allow_failed) { m_timing_allow_failed = timing_allow_failed; }
  237. [[nodiscard]] URL::URL& url();
  238. [[nodiscard]] URL::URL const& url() const;
  239. [[nodiscard]] URL::URL& current_url();
  240. [[nodiscard]] URL::URL const& current_url() const;
  241. void set_url(URL::URL url);
  242. [[nodiscard]] bool destination_is_script_like() const;
  243. [[nodiscard]] bool is_subresource_request() const;
  244. [[nodiscard]] bool is_non_subresource_request() const;
  245. [[nodiscard]] bool is_navigation_request() const;
  246. [[nodiscard]] bool has_redirect_tainted_origin() const;
  247. [[nodiscard]] String serialize_origin() const;
  248. [[nodiscard]] ByteBuffer byte_serialize_origin() const;
  249. [[nodiscard]] JS::NonnullGCPtr<Request> clone(JS::Realm&) const;
  250. void add_range_header(u64 first, Optional<u64> const& last);
  251. void add_origin_header();
  252. [[nodiscard]] bool cross_origin_embedder_policy_allows_credentials() const;
  253. // Non-standard
  254. void add_pending_response(Badge<Fetching::PendingResponse>, JS::NonnullGCPtr<Fetching::PendingResponse> pending_response)
  255. {
  256. VERIFY(!m_pending_responses.contains_slow(pending_response));
  257. m_pending_responses.append(pending_response);
  258. }
  259. void remove_pending_response(Badge<Fetching::PendingResponse>, JS::NonnullGCPtr<Fetching::PendingResponse> pending_response)
  260. {
  261. m_pending_responses.remove_first_matching([&](auto gc_ptr) { return gc_ptr == pending_response; });
  262. }
  263. [[nodiscard]] BufferPolicy buffer_policy() const { return m_buffer_policy; }
  264. void set_buffer_policy(BufferPolicy buffer_policy) { m_buffer_policy = buffer_policy; }
  265. private:
  266. explicit Request(JS::NonnullGCPtr<HeaderList>);
  267. virtual void visit_edges(JS::Cell::Visitor&) override;
  268. // https://fetch.spec.whatwg.org/#concept-request-method
  269. // A request has an associated method (a method). Unless stated otherwise it is `GET`.
  270. ByteBuffer m_method { ByteBuffer::copy("GET"sv.bytes()).release_value() };
  271. // https://fetch.spec.whatwg.org/#local-urls-only-flag
  272. // A request has an associated local-URLs-only flag. Unless stated otherwise it is unset.
  273. bool m_local_urls_only { false };
  274. // https://fetch.spec.whatwg.org/#concept-request-header-list
  275. // A request has an associated header list (a header list). Unless stated otherwise it is empty.
  276. JS::NonnullGCPtr<HeaderList> m_header_list;
  277. // https://fetch.spec.whatwg.org/#unsafe-request-flag
  278. // A request has an associated unsafe-request flag. Unless stated otherwise it is unset.
  279. bool m_unsafe_request { false };
  280. // https://fetch.spec.whatwg.org/#concept-request-body
  281. // A request has an associated body (null, a byte sequence, or a body). Unless stated otherwise it is null.
  282. BodyType m_body;
  283. // https://fetch.spec.whatwg.org/#concept-request-client
  284. // A request has an associated client (null or an environment settings object).
  285. JS::GCPtr<HTML::EnvironmentSettingsObject> m_client;
  286. // https://fetch.spec.whatwg.org/#concept-request-reserved-client
  287. // A request has an associated reserved client (null, an environment, or an environment settings object). Unless
  288. // stated otherwise it is null.
  289. ReservedClientType m_reserved_client;
  290. // https://fetch.spec.whatwg.org/#concept-request-replaces-client-id
  291. // A request has an associated replaces client id (a string). Unless stated otherwise it is the empty string.
  292. String m_replaces_client_id;
  293. // https://fetch.spec.whatwg.org/#concept-request-window
  294. // A request has an associated window ("no-window", "client", or an environment settings object whose global object
  295. // is a Window object). Unless stated otherwise it is "client".
  296. WindowType m_window { Window::Client };
  297. // https://fetch.spec.whatwg.org/#request-keepalive-flag
  298. // A request has an associated boolean keepalive. Unless stated otherwise it is false.
  299. bool m_keepalive { false };
  300. // https://fetch.spec.whatwg.org/#request-initiator-type
  301. // A request has an associated initiator type, which is null, "audio", "beacon", "body", "css", "early-hint",
  302. // "embed", "fetch", "font", "frame", "iframe", "image", "img", "input", "link", "object", "ping", "script",
  303. // "track", "video", "xmlhttprequest", or "other". Unless stated otherwise it is null. [RESOURCE-TIMING]
  304. Optional<InitiatorType> m_initiator_type;
  305. // https://fetch.spec.whatwg.org/#request-service-workers-mode
  306. // A request has an associated service-workers mode, that is "all" or "none". Unless stated otherwise it is "all".
  307. ServiceWorkersMode m_service_workers_mode { ServiceWorkersMode::All };
  308. // https://fetch.spec.whatwg.org/#concept-request-initiator
  309. // A request has an associated initiator, which is the empty string, "download", "imageset", "manifest",
  310. // "prefetch", "prerender", or "xslt". Unless stated otherwise it is the empty string.
  311. Optional<Initiator> m_initiator;
  312. // https://fetch.spec.whatwg.org/#concept-request-destination
  313. // A request has an associated destination, which is the empty string, "audio", "audioworklet", "document",
  314. // "embed", "font", "frame", "iframe", "image", "json", "manifest", "object", "paintworklet", "report", "script",
  315. // "serviceworker", "sharedworker", "style", "track", "video", "webidentity", "worker", or "xslt". Unless stated
  316. // otherwise it is the empty string.
  317. // NOTE: These are reflected on RequestDestination except for "serviceworker" and "webidentity" as fetches with
  318. // those destinations skip service workers.
  319. Optional<Destination> m_destination;
  320. // https://fetch.spec.whatwg.org/#request-priority
  321. // A request has an associated priority, which is "high", "low", or "auto". Unless stated otherwise it is "auto".
  322. Priority m_priority { Priority::Auto };
  323. // https://fetch.spec.whatwg.org/#request-internal-priority
  324. // A request has an associated internal priority (null or an implementation-defined object). Unless otherwise stated it is null.
  325. Optional<InternalPriority> m_internal_priority;
  326. // https://fetch.spec.whatwg.org/#concept-request-origin
  327. // A request has an associated origin, which is "client" or an origin. Unless stated otherwise it is "client".
  328. OriginType m_origin { Origin::Client };
  329. // https://fetch.spec.whatwg.org/#concept-request-policy-container
  330. // A request has an associated policy container, which is "client" or a policy container. Unless stated otherwise
  331. // it is "client".
  332. PolicyContainerType m_policy_container { PolicyContainer::Client };
  333. // https://fetch.spec.whatwg.org/#concept-request-referrer
  334. // A request has an associated referrer, which is "no-referrer", "client", or a URL. Unless stated otherwise it is
  335. // "client".
  336. ReferrerType m_referrer { Referrer::Client };
  337. // https://fetch.spec.whatwg.org/#concept-request-referrer-policy
  338. // A request has an associated referrer policy, which is a referrer policy. Unless stated otherwise it is the empty
  339. // string.
  340. ReferrerPolicy::ReferrerPolicy m_referrer_policy { ReferrerPolicy::ReferrerPolicy::EmptyString };
  341. // https://fetch.spec.whatwg.org/#concept-request-mode
  342. // A request has an associated mode, which is "same-origin", "cors", "no-cors", "navigate", or "websocket". Unless
  343. // stated otherwise, it is "no-cors".
  344. Mode m_mode { Mode::NoCORS };
  345. // https://fetch.spec.whatwg.org/#use-cors-preflight-flag
  346. // A request has an associated use-CORS-preflight flag. Unless stated otherwise, it is unset.
  347. bool m_use_cors_preflight { false };
  348. // https://fetch.spec.whatwg.org/#concept-request-credentials-mode
  349. // A request has an associated credentials mode, which is "omit", "same-origin", or "include". Unless stated
  350. // otherwise, it is "same-origin".
  351. CredentialsMode m_credentials_mode { CredentialsMode::SameOrigin };
  352. // https://fetch.spec.whatwg.org/#concept-request-use-url-credentials-flag
  353. // A request has an associated use-URL-credentials flag. Unless stated otherwise, it is unset.
  354. // NOTE: When this flag is set, when a request’s URL has a username and password, and there is an available
  355. // authentication entry for the request, then the URL’s credentials are preferred over that of the
  356. // authentication entry. Modern specifications avoid setting this flag, since putting credentials in URLs is
  357. // discouraged, but some older features set it for compatibility reasons.
  358. bool m_use_url_credentials { false };
  359. // https://fetch.spec.whatwg.org/#concept-request-cache-mode
  360. // A request has an associated cache mode, which is "default", "no-store", "reload", "no-cache", "force-cache", or
  361. // "only-if-cached". Unless stated otherwise, it is "default".
  362. CacheMode m_cache_mode { CacheMode::Default };
  363. // https://fetch.spec.whatwg.org/#concept-request-redirect-mode
  364. // A request has an associated redirect mode, which is "follow", "error", or "manual". Unless stated otherwise, it
  365. // is "follow".
  366. RedirectMode m_redirect_mode { RedirectMode::Follow };
  367. // https://fetch.spec.whatwg.org/#concept-request-integrity-metadata
  368. // A request has associated integrity metadata (a string). Unless stated otherwise, it is the empty string.
  369. String m_integrity_metadata;
  370. // https://fetch.spec.whatwg.org/#concept-request-nonce-metadata
  371. // A request has associated cryptographic nonce metadata (a string). Unless stated otherwise, it is the empty
  372. // string.
  373. String m_cryptographic_nonce_metadata;
  374. // https://fetch.spec.whatwg.org/#concept-request-parser-metadata
  375. // A request has associated parser metadata which is the empty string, "parser-inserted", or
  376. // "not-parser-inserted". Unless otherwise stated, it is the empty string.
  377. Optional<ParserMetadata> m_parser_metadata;
  378. // https://fetch.spec.whatwg.org/#concept-request-reload-navigation-flag
  379. // A request has an associated reload-navigation flag. Unless stated otherwise, it is unset.
  380. bool m_reload_navigation { false };
  381. // https://fetch.spec.whatwg.org/#concept-request-history-navigation-flag
  382. // A request has an associated history-navigation flag. Unless stated otherwise, it is unset.
  383. bool m_history_navigation { false };
  384. // https://fetch.spec.whatwg.org/#request-user-activation
  385. // A request has an associated boolean user-activation. Unless stated otherwise, it is false.
  386. bool m_user_activation { false };
  387. // https://fetch.spec.whatwg.org/#request-render-blocking
  388. // A request has an associated boolean render-blocking. Unless stated otherwise, it is false.
  389. bool m_render_blocking { false };
  390. // https://fetch.spec.whatwg.org/#concept-request-url-list
  391. // A request has an associated URL list (a list of one or more URLs). Unless stated otherwise, it is a list
  392. // containing a copy of request’s URL.
  393. Vector<URL::URL> m_url_list;
  394. // https://fetch.spec.whatwg.org/#concept-request-redirect-count
  395. // A request has an associated redirect count. Unless stated otherwise, it is zero.
  396. // NOTE: '4.4. HTTP-redirect fetch' infers a limit of 20.
  397. u8 m_redirect_count { 0 };
  398. // https://fetch.spec.whatwg.org/#concept-request-response-tainting
  399. // A request has an associated response tainting, which is "basic", "cors", or "opaque". Unless stated otherwise,
  400. // it is "basic".
  401. ResponseTainting m_response_tainting { ResponseTainting::Basic };
  402. // https://fetch.spec.whatwg.org/#no-cache-prevent-cache-control
  403. // A request has an associated prevent no-cache cache-control header modification flag. Unless stated otherwise, it
  404. // is unset.
  405. bool m_prevent_no_cache_cache_control_header_modification { false };
  406. // https://fetch.spec.whatwg.org/#done-flag
  407. // A request has an associated done flag. Unless stated otherwise, it is unset.
  408. bool m_done { false };
  409. // https://fetch.spec.whatwg.org/#timing-allow-failed
  410. // A request has an associated timing allow failed flag. Unless stated otherwise, it is unset.
  411. bool m_timing_allow_failed { false };
  412. // Non-standard
  413. Vector<JS::NonnullGCPtr<Fetching::PendingResponse>> m_pending_responses;
  414. BufferPolicy m_buffer_policy { BufferPolicy::BufferResponse };
  415. };
  416. StringView request_destination_to_string(Request::Destination);
  417. StringView request_mode_to_string(Request::Mode);
  418. Optional<Request::Priority> request_priority_from_string(StringView);
  419. }