Skip to content

Commit bb95051

Browse files
committed
refactor(fetch): use Option<Vec<u8>> for request body handling and remove HasBody extension
1 parent e979d67 commit bb95051

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

core/runtime/src/fetch/request.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ pub struct RequestInit {
2525
signal: Option<JsObject>,
2626
}
2727

28-
#[derive(Clone, Copy)]
29-
struct HasBody;
30-
3128
impl RequestInit {
3229
/// Takes the abort signal from the options, if present.
3330
pub fn take_signal(&mut self) -> Option<JsObject> {
@@ -45,13 +42,15 @@ impl RequestInit {
4542
) -> JsResult<HttpRequest<Vec<u8>>> {
4643
let mut builder = HttpRequest::builder();
4744
let mut is_get_or_head_method = true;
48-
let mut has_inherited_body = false;
49-
let mut request_body = Vec::new();
45+
let mut inherited_is_get_or_head_method = true;
46+
let mut inherited_body = None;
47+
let mut request_body: Option<Vec<u8>> = None;
5048
if let Some(r) = request {
5149
let (parts, body) = r.into_parts();
5250
is_get_or_head_method = matches!(parts.method, http::Method::GET | http::Method::HEAD);
51+
inherited_is_get_or_head_method = is_get_or_head_method;
5352
// https://fetch.spec.whatwg.org/#dom-request - "Let inputBody be input's request's body if input is a Request object; otherwise null."
54-
has_inherited_body = parts.extensions.get::<HasBody>().is_some() || !body.is_empty();
53+
inherited_body = Some(body);
5554
builder = builder
5655
.method(parts.method)
5756
.uri(parts.uri)
@@ -60,7 +59,6 @@ impl RequestInit {
6059
for (key, value) in &parts.headers {
6160
builder = builder.header(key, value);
6261
}
63-
request_body = body;
6462
}
6563

6664
if let Some(headers) = self.headers.take() {
@@ -78,8 +76,16 @@ impl RequestInit {
7876
builder = builder.method(method.as_str());
7977
}
8078

81-
// https://fetch.spec.whatwg.org/#dom-request - "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."
82-
if is_get_or_head_method && (self.body.is_some() || has_inherited_body) {
79+
// Fetch Standard §5.4 Request constructor:
80+
// If either init["body"] exists and is non-null or inputBody is non-null,
81+
// and request's method is GET or HEAD, then throw a TypeError.
82+
// https://fetch.spec.whatwg.org/#dom-request
83+
if is_get_or_head_method
84+
&& (self.body.is_some()
85+
|| inherited_body
86+
.as_ref()
87+
.is_some_and(|body| !body.is_empty() || !inherited_is_get_or_head_method))
88+
{
8389
return Err(js_error!(TypeError: "Request with GET/HEAD method cannot have body."));
8490
}
8591

@@ -89,20 +95,19 @@ impl RequestInit {
8995
let body = body.to_std_string().map_err(
9096
|_| js_error!(TypeError: "Request constructor: body is not a valid string"),
9197
)?;
92-
request_body = body.into_bytes();
98+
request_body = Some(body.into_bytes());
9399
} else {
94100
return Err(
95101
js_error!(TypeError: "Request constructor: body is not a supported type"),
96102
);
97103
}
104+
} else if let Some(body) = inherited_body {
105+
request_body = Some(body);
98106
}
99107

100-
let mut request = builder
101-
.body(request_body)
108+
let request = builder
109+
.body(request_body.unwrap_or_default())
102110
.map_err(|_| js_error!(Error: "Cannot construct request"))?;
103-
if self.body.is_some() || has_inherited_body {
104-
request.extensions_mut().insert(HasBody);
105-
}
106111
Ok(request)
107112
}
108113
}

0 commit comments

Comments
 (0)