LibWeb: Add URLSearchParams as part of union type for XHR::send()

This patch adds support for URLSearchParams to XHR::send() and
introduces the union type XMLHttpRequestBodyInit.

XHR::send() now has support for String and URLSearchParams.
This commit is contained in:
Kenneth Myhra 2022-07-07 23:15:41 +02:00 committed by Linus Groh
parent bd74db157a
commit 247951e09c
Notes: sideshowbarker 2024-07-17 09:36:40 +09:00
4 changed files with 40 additions and 5 deletions

View file

@ -52,6 +52,8 @@ static bool is_wrappable_type(Type const& type)
return true;
if (type.name == "WebGLRenderingContext")
return true;
if (type.name == "URLSearchParams")
return true;
return false;
}

View file

@ -3,6 +3,7 @@
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
* Copyright (c) 2022, Kenneth Myhra <kennethmyhra@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -426,6 +427,21 @@ static bool is_header_value(String const& header_value)
return true;
}
static XMLHttpRequest::BodyWithType safely_extract_body(XMLHttpRequestBodyInit& body)
{
if (body.has<NonnullRefPtr<URL::URLSearchParams>>()) {
return {
body.get<NonnullRefPtr<URL::URLSearchParams>>()->to_string().to_byte_buffer(),
"application/x-www-form-urlencoded;charset=UTF-8"
};
}
VERIFY(body.has<String>());
return {
body.get<String>().to_byte_buffer(),
"text/plain;charset=UTF-8"
};
}
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-setrequestheader
DOM::ExceptionOr<void> XMLHttpRequest::set_request_header(String const& name, String const& value)
{
@ -547,7 +563,7 @@ DOM::ExceptionOr<void> XMLHttpRequest::open(String const& method, String const&
}
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-send
DOM::ExceptionOr<void> XMLHttpRequest::send(String body)
DOM::ExceptionOr<void> XMLHttpRequest::send(Optional<XMLHttpRequestBodyInit> body)
{
if (m_ready_state != ReadyState::Opened)
return DOM::InvalidStateError::create("XHR readyState is not OPENED");
@ -559,6 +575,8 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(String body)
if (m_method.is_one_of("GET"sv, "HEAD"sv))
body = {};
auto body_with_type = body.has_value() ? safely_extract_body(body.value()) : XMLHttpRequest::BodyWithType {};
AK::URL request_url = m_window->associated_document().parse_url(m_url.to_string());
dbgln("XHR send from {} to {}", m_window->associated_document().url(), request_url);
@ -578,8 +596,11 @@ DOM::ExceptionOr<void> XMLHttpRequest::send(String body)
auto request = LoadRequest::create_for_url_on_page(request_url, m_window->page());
request.set_method(m_method);
if (!body.is_null())
request.set_body(body.to_byte_buffer());
if (!body_with_type.body.is_empty()) {
request.set_body(body_with_type.body);
if (!body_with_type.type.is_empty())
request.set_header("Content-Type", body_with_type.type);
}
for (auto& it : m_request_headers)
request.set_header(it.key, it.value);

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Kenneth Myhra <kennethmyhra@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -15,12 +16,15 @@
#include <LibWeb/DOM/EventTarget.h>
#include <LibWeb/DOM/ExceptionOr.h>
#include <LibWeb/MimeSniff/MimeType.h>
#include <LibWeb/URL/URLSearchParams.h>
#include <LibWeb/XHR/XMLHttpRequestEventTarget.h>
namespace Web::XHR {
static constexpr Array<u8, 4> http_whitespace_bytes = { '\t', '\n', '\r', ' ' };
using XMLHttpRequestBodyInit = Variant<NonnullRefPtr<URL::URLSearchParams>, String>;
class XMLHttpRequest final
: public RefCounted<XMLHttpRequest>
, public Weakable<XMLHttpRequest>
@ -34,6 +38,11 @@ public:
Done = 4,
};
struct BodyWithType {
ByteBuffer body;
String type;
};
using WrapperType = Bindings::XMLHttpRequestWrapper;
static NonnullRefPtr<XMLHttpRequest> create(HTML::Window& window)
@ -58,7 +67,7 @@ public:
DOM::ExceptionOr<void> open(String const& method, String const& url);
DOM::ExceptionOr<void> open(String const& method, String const& url, bool async, String const& username = {}, String const& password = {});
DOM::ExceptionOr<void> send(String body);
DOM::ExceptionOr<void> send(Optional<XMLHttpRequestBodyInit> body);
DOM::ExceptionOr<void> set_request_header(String const& header, String const& value);
void set_response_type(Bindings::XMLHttpRequestResponseType type) { m_response_type = type; }

View file

@ -1,5 +1,8 @@
#import <XHR/XMLHttpRequestEventTarget.idl>
#import <DOM/EventHandler.idl>
#import <URL/URLSearchParams.idl>
typedef (URLSearchParams or USVString) XMLHttpRequestBodyInit;
enum XMLHttpRequestResponseType {
"",
@ -30,7 +33,7 @@ interface XMLHttpRequest : XMLHttpRequestEventTarget {
undefined open(DOMString method, DOMString url);
undefined open(ByteString method, USVString url, boolean async, optional USVString? username = {}, optional USVString? password = {});
undefined setRequestHeader(DOMString name, DOMString value);
undefined send(optional USVString body = {});
undefined send(optional XMLHttpRequestBodyInit? body = null);
ByteString? getResponseHeader(ByteString name);
ByteString getAllResponseHeaders();