fix(fetch): reject Request body for GET and HEAD methods#5201
fix(fetch): reject Request body for GET and HEAD methods#5201HiteshShonak wants to merge 10 commits intoboa-dev:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR aligns Boa’s Request constructor with the Fetch Standard by rejecting request bodies for GET and HEAD methods, addressing issue #5200.
Changes:
- Add a
GET/HEAD+ body validation inRequestInit::into_request_builder, returning aTypeErrorwhen violated. - Add regression tests asserting
new Request(..., { method: "GET"/"HEAD", body: "x" })throws aTypeError.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| core/runtime/src/fetch/request.rs | Adds GET/HEAD body rejection logic during request construction. |
| core/runtime/src/fetch/tests/request.rs | Adds regression tests for GET/HEAD requests with an explicit body. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Test262 conformance changes
Tested main commit: |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5201 +/- ##
===========================================
+ Coverage 47.24% 59.78% +12.54%
===========================================
Files 476 590 +114
Lines 46892 63701 +16809
===========================================
+ Hits 22154 38086 +15932
- Misses 24738 25615 +877 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
core/runtime/src/fetch/request.rs
Outdated
| is_get_or_head_method = matches!(parts.method, http::Method::GET | http::Method::HEAD); | ||
| has_inherited_body = parts.extensions.get::<HasBody>().is_some() || !body.is_empty(); |
There was a problem hiding this comment.
Can you link the specific part of the spec that handles inherited bodies? I was looking through it and I didn't see it doing this. The only thing it checked was the parent request and the RequestInit object.
There was a problem hiding this comment.
In general I would like to see this being commented with the specific spec lines it's implementing, since it makes maintainance much easier.
There was a problem hiding this comment.
hey, added spec comments to both places. the HasBody extension is there because boa stores body as Vec, so an empty string body and no body both look the same. needed a way to track if body was explicitly set, which is what inputBody is non-null checks in the spec: https://fetch.spec.whatwg.org/#dom-request
There was a problem hiding this comment.
That sounds kinda suboptimal. What about just changing body to an Option<Vec<u8>>? That avoids having to use an extension to something that should be "native" in a way.
There was a problem hiding this comment.
switched to Option<Vec<u8>> and removed the HasBody extension. let me know if this looks good
…move HasBody extension
core/runtime/src/fetch/request.rs
Outdated
| let mut is_get_or_head_method = true; | ||
| let mut inherited_is_get_or_head_method = true; | ||
| let mut inherited_body = None; | ||
| let mut request_body: Option<Vec<u8>> = None; |
There was a problem hiding this comment.
I'm slightly confused about using all these flags. As far as I understand you just need inherited_body, and the rest can be inlined into the specific part of the code using them, since they're mostly used only once.
There was a problem hiding this comment.
request_body doesn't need to exist here, you can put it below by using a let-if block:
let request_body = if let Some(body) = &self.body {
// ...
} else {
input_body
};There was a problem hiding this comment.
simplified this and inlined the extra flags, and moved request_body into the let-if block as suggested
core/runtime/src/fetch/request.rs
Outdated
| if is_get_or_head_method | ||
| && (self.body.is_some() | ||
| || inherited_body | ||
| .as_ref() | ||
| .is_some_and(|body| !body.is_empty() || !inherited_is_get_or_head_method)) |
There was a problem hiding this comment.
Why inherited_body also checks that the body is empty? I thought this would throw even if the body is empty, since the spec is checking if the body is null, not if it's empty.
This change would also considerably simplify the code:
let is_get_or_head_method = method.eq_ignore_ascii_case("GET") || method.eq_ignore_ascii_case("HEAD");
if is_get_or_head_method && (self.body.is_some() || inherited_body.is_some() {
// throw error
}There was a problem hiding this comment.
removed the empty-body check here and switched to the simplified null/non-null check
This Pull Request fixes/closes #5200.
It changes the following:
into_request_buildernow checks if the method isGETorHEADand throws aTypeErrorif a body is provided, matching the Fetch Standard.GETandHEADcases.Testing:
cargo test -p boa_runtime request -- --nocaptureSpec reference: https://fetch.spec.whatwg.org/#dom-request