Skip to content

Commit a2acfa6

Browse files
authored
fix(fetch): reject forbidden HTTP methods CONNECT, TRACE, and TRACK (#5203)
This Pull Request fixes/closes #5202. It changes the following: - Reject `CONNECT`, `TRACE`, and `TRACK` methods in the `Request` constructor and throw a `TypeError`, matching the Fetch Standard. - Check is case-insensitive, so `connect`, `trace`, `track` are also rejected. - Added regression tests for all three forbidden methods. Testing: ```bash cargo test -p boa_runtime request -- --nocapture ``` Spec reference: https://fetch.spec.whatwg.org/#forbidden-method
1 parent d6d76d8 commit a2acfa6

2 files changed

Lines changed: 43 additions & 2 deletions

File tree

core/runtime/src/fetch/request.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,27 @@ impl RequestInit {
6262
}
6363

6464
if let Some(Convert(ref method)) = self.method.take() {
65-
builder = builder.method(method.to_std_string().map_err(
65+
let method = method.to_std_string().map_err(
6666
|_| js_error!(TypeError: "Request constructor: {} is an invalid method", method.to_std_string_escaped()),
67-
)?.as_str());
67+
)?;
68+
69+
// 25. If init["method"] exists, then:
70+
// 1. Let method be init["method"].
71+
// 2. If method is not a method or method is a forbidden method, throw a TypeError.
72+
// 3. Normalize method.
73+
// 4. Set request's method to method.
74+
// https://fetch.spec.whatwg.org/#dom-request
75+
if method.eq_ignore_ascii_case("CONNECT")
76+
|| method.eq_ignore_ascii_case("TRACE")
77+
|| method.eq_ignore_ascii_case("TRACK")
78+
{
79+
return Err(js_error!(
80+
TypeError: "'{}' HTTP method is unsupported.",
81+
method
82+
));
83+
}
84+
85+
builder = builder.method(method.as_str());
6886
}
6987

7088
if let Some(body) = &self.body {

core/runtime/src/fetch/tests/request.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::test::{TestAction, run_test_actions};
55
use boa_engine::{JsObject, js_str, js_string};
66
use either::Either;
77
use http::{Response, Uri};
8+
use indoc::indoc;
89

910
#[test]
1011
fn request_constructor() {
@@ -48,6 +49,28 @@ fn request_constructor() {
4849
]);
4950
}
5051

52+
#[test]
53+
fn request_constructor_forbidden_method_throws() {
54+
run_test_actions([
55+
TestAction::inspect_context(|ctx| {
56+
let fetcher = TestFetcher::default();
57+
crate::fetch::register(fetcher, None, ctx).expect("failed to register fetch");
58+
}),
59+
TestAction::run(indoc! {r#"
60+
for (const method of ["CONNECT", "TRACE", "TRACK", "connect"]) {
61+
try {
62+
new Request("http://unit.test", { method });
63+
throw Error("expected the call above to throw");
64+
} catch (e) {
65+
if (!(e instanceof TypeError)) {
66+
throw e;
67+
}
68+
}
69+
}
70+
"#}),
71+
]);
72+
}
73+
5174
#[test]
5275
fn request_clone_preserves_body_without_override() {
5376
run_test_actions([

0 commit comments

Comments
 (0)