mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
The end goal here is for LibHTTP to be the home of our RFC 9111 (HTTP caching) implementation. We currently have one implementation in LibWeb for our in-memory cache and another in RequestServer for our disk cache. The implementations both largely revolve around interacting with HTTP headers. But in LibWeb, we are using Fetch's header infra, and in RS we are using are home-grown header infra from LibHTTP. So to give these a common denominator, this patch replaces the LibHTTP implementation with Fetch's infra. Our existing LibHTTP implementation was not particularly compliant with any spec, so this at least gives us a standards-based common implementation. This migration also required moving a handful of other Fetch AOs over to LibHTTP. (It turns out these AOs were all from the Fetch/Infra/HTTP folder, so perhaps it makes sense for LibHTTP to be the implementation of that entire set of facilities.)
206 lines
7.4 KiB
C++
206 lines
7.4 KiB
C++
/*
|
|
* Copyright (c) 2020-2021, Andreas Kling <andreas@ladybird.org>
|
|
* Copyright (c) 2022, Kenneth Myhra <kennethmyhra@serenityos.org>
|
|
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/ByteBuffer.h>
|
|
#include <AK/RefCounted.h>
|
|
#include <AK/Weakable.h>
|
|
#include <LibHTTP/HeaderList.h>
|
|
#include <LibURL/URL.h>
|
|
#include <LibWeb/DOM/EventTarget.h>
|
|
#include <LibWeb/DOMURL/URLSearchParams.h>
|
|
#include <LibWeb/Fetch/BodyInit.h>
|
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Bodies.h>
|
|
#include <LibWeb/Fetch/Infrastructure/HTTP/Statuses.h>
|
|
#include <LibWeb/HTML/Window.h>
|
|
#include <LibWeb/MimeSniff/MimeType.h>
|
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
|
#include <LibWeb/XHR/XMLHttpRequestEventTarget.h>
|
|
|
|
namespace Web::XHR {
|
|
|
|
// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit
|
|
using DocumentOrXMLHttpRequestBodyInit = Variant<GC::Root<Web::DOM::Document>, GC::Root<Web::FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<Web::DOMURL::URLSearchParams>, AK::String>;
|
|
|
|
class XMLHttpRequest final : public XMLHttpRequestEventTarget {
|
|
WEB_PLATFORM_OBJECT(XMLHttpRequest, XMLHttpRequestEventTarget);
|
|
GC_DECLARE_ALLOCATOR(XMLHttpRequest);
|
|
|
|
public:
|
|
enum class State : u16 {
|
|
Unsent = 0,
|
|
Opened = 1,
|
|
HeadersReceived = 2,
|
|
Loading = 3,
|
|
Done = 4,
|
|
};
|
|
|
|
static WebIDL::ExceptionOr<GC::Ref<XMLHttpRequest>> construct_impl(JS::Realm&);
|
|
|
|
virtual ~XMLHttpRequest() override;
|
|
|
|
State ready_state() const { return m_state; }
|
|
Fetch::Infrastructure::Status status() const;
|
|
WebIDL::ExceptionOr<String> status_text() const;
|
|
WebIDL::ExceptionOr<String> response_text() const;
|
|
WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> response_xml();
|
|
WebIDL::ExceptionOr<JS::Value> response();
|
|
Bindings::XMLHttpRequestResponseType response_type() const { return m_response_type; }
|
|
String response_url();
|
|
|
|
WebIDL::ExceptionOr<void> open(String const& method, String const& url);
|
|
WebIDL::ExceptionOr<void> open(String const& method, String const& url, bool async, Optional<String> const& username = Optional<String> {}, Optional<String> const& password = Optional<String> {});
|
|
WebIDL::ExceptionOr<void> send(Optional<DocumentOrXMLHttpRequestBodyInit> body);
|
|
|
|
WebIDL::ExceptionOr<void> set_request_header(String const& name, String const& value);
|
|
WebIDL::ExceptionOr<void> set_response_type(Bindings::XMLHttpRequestResponseType);
|
|
|
|
Optional<String> get_response_header(String const& name) const;
|
|
String get_all_response_headers() const;
|
|
|
|
WebIDL::CallbackType* onreadystatechange();
|
|
void set_onreadystatechange(WebIDL::CallbackType*);
|
|
|
|
WebIDL::ExceptionOr<void> override_mime_type(String const& mime);
|
|
|
|
u32 timeout() const;
|
|
WebIDL::ExceptionOr<void> set_timeout(u32 timeout);
|
|
|
|
bool with_credentials() const;
|
|
WebIDL::ExceptionOr<void> set_with_credentials(bool);
|
|
|
|
void abort();
|
|
|
|
GC::Ref<XMLHttpRequestUpload> upload() const;
|
|
|
|
private:
|
|
virtual void initialize(JS::Realm&) override;
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
|
virtual bool must_survive_garbage_collection() const override;
|
|
|
|
[[nodiscard]] MimeSniff::MimeType get_response_mime_type() const;
|
|
[[nodiscard]] Optional<StringView> get_final_encoding() const;
|
|
[[nodiscard]] MimeSniff::MimeType get_final_mime_type() const;
|
|
|
|
String get_text_response() const;
|
|
void set_document_response();
|
|
|
|
WebIDL::ExceptionOr<void> handle_response_end_of_body();
|
|
WebIDL::ExceptionOr<void> handle_errors();
|
|
JS::ThrowCompletionOr<void> request_error_steps(FlyString const& event_name, GC::Ptr<WebIDL::DOMException> exception = nullptr);
|
|
|
|
XMLHttpRequest(JS::Realm&, XMLHttpRequestUpload&, NonnullRefPtr<HTTP::HeaderList>, Fetch::Infrastructure::Response&, Fetch::Infrastructure::FetchController&);
|
|
|
|
// https://xhr.spec.whatwg.org/#upload-object
|
|
// upload object
|
|
// An XMLHttpRequestUpload object.
|
|
GC::Ref<XMLHttpRequestUpload> m_upload_object;
|
|
|
|
// https://xhr.spec.whatwg.org/#concept-xmlhttprequest-state
|
|
// state
|
|
// One of unsent, opened, headers received, loading, and done; initially unsent.
|
|
State m_state { State::Unsent };
|
|
|
|
// https://xhr.spec.whatwg.org/#send-flag
|
|
// send() flag
|
|
// A flag, initially unset.
|
|
bool m_send { false };
|
|
|
|
// https://xhr.spec.whatwg.org/#timeout
|
|
// timeout
|
|
// An unsigned integer, initially 0.
|
|
u32 m_timeout { 0 };
|
|
|
|
// https://xhr.spec.whatwg.org/#cross-origin-credentials
|
|
// cross-origin credentials
|
|
// A boolean, initially false.
|
|
bool m_cross_origin_credentials { false };
|
|
|
|
// https://xhr.spec.whatwg.org/#request-method
|
|
// request method
|
|
// A method.
|
|
ByteString m_request_method;
|
|
|
|
// https://xhr.spec.whatwg.org/#request-url
|
|
// request URL
|
|
// A URL.
|
|
URL::URL m_request_url;
|
|
|
|
// https://xhr.spec.whatwg.org/#author-request-headers
|
|
// author request headers
|
|
// A header list, initially empty.
|
|
NonnullRefPtr<HTTP::HeaderList> m_author_request_headers;
|
|
|
|
// https://xhr.spec.whatwg.org/#request-body
|
|
// request body
|
|
// Initially null.
|
|
GC::Ptr<Fetch::Infrastructure::Body> m_request_body;
|
|
|
|
// https://xhr.spec.whatwg.org/#synchronous-flag
|
|
// synchronous flag
|
|
// A flag, initially unset.
|
|
bool m_synchronous { false };
|
|
|
|
// https://xhr.spec.whatwg.org/#upload-complete-flag
|
|
// upload complete flag
|
|
// A flag, initially unset.
|
|
bool m_upload_complete { false };
|
|
|
|
// https://xhr.spec.whatwg.org/#upload-listener-flag
|
|
// upload listener flag
|
|
// A flag, initially unset.
|
|
bool m_upload_listener { false };
|
|
|
|
// https://xhr.spec.whatwg.org/#timed-out-flag
|
|
// timed out flag
|
|
// A flag, initially unset.
|
|
bool m_timed_out { false };
|
|
|
|
// https://xhr.spec.whatwg.org/#response
|
|
// response
|
|
// A response, initially a network error.
|
|
GC::Ref<Fetch::Infrastructure::Response> m_response;
|
|
|
|
// https://xhr.spec.whatwg.org/#received-bytes
|
|
// received bytes
|
|
// A byte sequence, initially the empty byte sequence.
|
|
ByteBuffer m_received_bytes;
|
|
|
|
// https://xhr.spec.whatwg.org/#response-type
|
|
// response type
|
|
// One of the empty string, "arraybuffer", "blob", "document", "json", and "text"; initially the empty string.
|
|
Bindings::XMLHttpRequestResponseType m_response_type;
|
|
|
|
enum class Failure {
|
|
/// ????
|
|
};
|
|
|
|
// https://xhr.spec.whatwg.org/#response-object
|
|
// response object
|
|
// An object, failure, or null, initially null.
|
|
// NOTE: This needs to be a JS::Value as the JSON response might not actually be an object.
|
|
Variant<GC::Ref<JS::Object>, Failure, Empty> m_response_object;
|
|
|
|
// https://xhr.spec.whatwg.org/#xmlhttprequest-fetch-controller
|
|
// fetch controller
|
|
// A fetch controller, initially a new fetch controller.
|
|
// NOTE: The send() method sets it to a useful fetch controller, but for simplicity it always holds a fetch controller.
|
|
GC::Ref<Fetch::Infrastructure::FetchController> m_fetch_controller;
|
|
|
|
// https://xhr.spec.whatwg.org/#override-mime-type
|
|
// override MIME type
|
|
// A MIME type or null, initially null.
|
|
// NOTE: Can get a value when overrideMimeType() is invoked.
|
|
Optional<MimeSniff::MimeType> m_override_mime_type;
|
|
|
|
// Non-standard, see async path in `send()`
|
|
u64 m_request_body_transmitted { 0 };
|
|
};
|
|
|
|
}
|