Skip to content

Commit 9adfa4b

Browse files
JakeChampionGuy Bedford
andauthored
add tests to confirm we normalise the HTTP method correctly when constructing a new Request (#888)
Co-authored-by: Guy Bedford <[email protected]>
1 parent 3b0fc81 commit 9adfa4b

File tree

9 files changed

+389
-27
lines changed

9 files changed

+389
-27
lines changed

integration-tests/js-compute/fixtures/app/src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import "./request-auto-decompress.js"
4040
import "./request-cache-key.js"
4141
import "./request-clone.js"
4242
import "./request-headers.js"
43+
import "./request-method.js"
4344
import "./response-json.js"
4445
import "./response-redirect.js"
4546
import "./response.js"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* eslint-env serviceworker */
2+
3+
import { pass, assert } from "./assertions.js";
4+
import { routes } from "./routes.js";
5+
6+
routes.set("/request/method/host", (event) => {
7+
return new Response('', {
8+
headers: {
9+
result: event.request.method
10+
}
11+
})
12+
});
13+
14+
routes.set("/request/method/guest", () => {
15+
const methods = [
16+
["get", "GET"],
17+
["GET", "GET"],
18+
["GeT", "GET"],
19+
["head", "HEAD"],
20+
["HEAD", "HEAD"],
21+
["HeaD", "HEAD"],
22+
["options", "OPTIONS"],
23+
["OPTIONS", "OPTIONS"],
24+
["OPtIOnS", "OPTIONS"],
25+
["post", "POST"],
26+
["POST", "POST"],
27+
["pOSt", "POST"],
28+
["put", "PUT"],
29+
["PUT", "PUT"],
30+
["Put", "PUT"],
31+
["delete", "DELETE"],
32+
["DELETE", "DELETE"],
33+
["DELete", "DELETE"],
34+
["hello", "hello"],
35+
["HELLO", "HELLO"],
36+
["HEllO", "HEllO"],
37+
// TODO: Add # $ % & when the platform supports them
38+
["!*+-.^_`|~1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", "!*+-.^_`|~1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"],
39+
];
40+
for (const [method, expected] of methods) {
41+
const result = new Request('http://a.a', { method: method }).method;
42+
const error = assert(result, expected, `new Request('http://a.a', {method: "${method}"}).method`)
43+
if (error) { return error }
44+
}
45+
return pass('ok')
46+
});

integration-tests/js-compute/fixtures/app/src/timers.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-env serviceworker */
22
import { pass, assert, assertDoesNotThrow, assertThrows } from "./assertions.js";
33
import { routes } from "./routes.js";
4+
import { CacheOverride } from "fastly:cache-override";
45

56
// setInterval
67
{
@@ -345,11 +346,13 @@ import { routes } from "./routes.js";
345346
routes.set('/setTimeout/fetch-timeout', async () => {
346347
let timedOut = false
347348
const first = fetch('https://httpbin.org/delay/1', {
348-
backend: 'httpbin'
349+
backend: 'httpbin',
350+
cacheOverride: new CacheOverride('pass')
349351
})
350352
const second = Promise.race([
351353
fetch('https://httpbin.org/delay/1', {
352-
backend: 'httpbin'
354+
backend: 'httpbin',
355+
cacheOverride: new CacheOverride('pass')
353356
}),
354357
new Promise(resolve => setTimeout(resolve, 5)).then(() => {
355358
timedOut = true

integration-tests/js-compute/fixtures/app/tests.json

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8735,5 +8735,280 @@
87358735
"status": 200,
87368736
"body": "ok"
87378737
}
8738+
},
8739+
"GET /request/method/host": {
8740+
"environments": ["compute", "viceroy"],
8741+
"downstream_request": {
8742+
"method": "GET",
8743+
"pathname": "/request/method/host"
8744+
},
8745+
"downstream_response": {
8746+
"status": 200,
8747+
"body": "",
8748+
"headers": [["result", "GET"]]
8749+
}
8750+
},
8751+
"get /request/method/host": {
8752+
"environments": ["compute", "viceroy"],
8753+
"downstream_request": {
8754+
"method": "get",
8755+
"pathname": "/request/method/host"
8756+
},
8757+
"downstream_response": {
8758+
"status": 200,
8759+
"body": "",
8760+
"headers": [["result", "GET"]]
8761+
}
8762+
},
8763+
"GeT /request/method/host": {
8764+
"environments": ["compute", "viceroy"],
8765+
"downstream_request": {
8766+
"method": "GeT",
8767+
"pathname": "/request/method/host"
8768+
},
8769+
"downstream_response": {
8770+
"status": 200,
8771+
"body": "",
8772+
"headers": [["result", "GET"]]
8773+
}
8774+
},
8775+
"HEAD /request/method/host": {
8776+
"environments": ["compute", "viceroy"],
8777+
"downstream_request": {
8778+
"method": "HEAD",
8779+
"pathname": "/request/method/host"
8780+
},
8781+
"downstream_response": {
8782+
"status": 200,
8783+
"body": "",
8784+
"headers": [["result", "HEAD"]]
8785+
}
8786+
},
8787+
"head /request/method/host": {
8788+
"environments": ["compute", "viceroy"],
8789+
"downstream_request": {
8790+
"method": "head",
8791+
"pathname": "/request/method/host"
8792+
},
8793+
"downstream_response": {
8794+
"status": 200,
8795+
"body": "",
8796+
"headers": [["result", "HEAD"]]
8797+
}
8798+
},
8799+
"HeAd /request/method/host": {
8800+
"environments": ["compute", "viceroy"],
8801+
"downstream_request": {
8802+
"method": "HeAd",
8803+
"pathname": "/request/method/host"
8804+
},
8805+
"downstream_response": {
8806+
"status": 200,
8807+
"body": "",
8808+
"headers": [["result", "HEAD"]]
8809+
}
8810+
},
8811+
"OPTIONS /request/method/host": {
8812+
"environments": ["compute", "viceroy"],
8813+
"downstream_request": {
8814+
"method": "OPTIONS",
8815+
"pathname": "/request/method/host"
8816+
},
8817+
"downstream_response": {
8818+
"status": 200,
8819+
"body": "",
8820+
"headers": [["result", "OPTIONS"]]
8821+
}
8822+
},
8823+
"OPTioNS /request/method/host": {
8824+
"environments": ["compute", "viceroy"],
8825+
"downstream_request": {
8826+
"method": "OPTioNS",
8827+
"pathname": "/request/method/host"
8828+
},
8829+
"downstream_response": {
8830+
"status": 200,
8831+
"body": "",
8832+
"headers": [["result", "OPTIONS"]]
8833+
}
8834+
},
8835+
"options /request/method/host": {
8836+
"environments": ["compute", "viceroy"],
8837+
"downstream_request": {
8838+
"method": "options",
8839+
"pathname": "/request/method/host"
8840+
},
8841+
"downstream_response": {
8842+
"status": 200,
8843+
"body": "",
8844+
"headers": [["result", "OPTIONS"]]
8845+
}
8846+
},
8847+
"POST /request/method/host": {
8848+
"environments": ["compute", "viceroy"],
8849+
"downstream_request": {
8850+
"method": "POST",
8851+
"pathname": "/request/method/host"
8852+
},
8853+
"downstream_response": {
8854+
"status": 200,
8855+
"body": "",
8856+
"headers": [["result", "POST"]]
8857+
}
8858+
},
8859+
"post /request/method/host": {
8860+
"environments": ["compute", "viceroy"],
8861+
"downstream_request": {
8862+
"method": "post",
8863+
"pathname": "/request/method/host"
8864+
},
8865+
"downstream_response": {
8866+
"status": 200,
8867+
"body": "",
8868+
"headers": [["result", "POST"]]
8869+
}
8870+
},
8871+
"PosT /request/method/host": {
8872+
"environments": ["compute", "viceroy"],
8873+
"downstream_request": {
8874+
"method": "PosT",
8875+
"pathname": "/request/method/host"
8876+
},
8877+
"downstream_response": {
8878+
"status": 200,
8879+
"body": "",
8880+
"headers": [["result", "POST"]]
8881+
}
8882+
},
8883+
"PUT /request/method/host": {
8884+
"environments": ["compute", "viceroy"],
8885+
"downstream_request": {
8886+
"method": "PUT",
8887+
"pathname": "/request/method/host"
8888+
},
8889+
"downstream_response": {
8890+
"status": 200,
8891+
"body": "",
8892+
"headers": [["result", "PUT"]]
8893+
}
8894+
},
8895+
"put /request/method/host": {
8896+
"environments": ["compute", "viceroy"],
8897+
"downstream_request": {
8898+
"method": "put",
8899+
"pathname": "/request/method/host"
8900+
},
8901+
"downstream_response": {
8902+
"status": 200,
8903+
"body": "",
8904+
"headers": [["result", "PUT"]]
8905+
}
8906+
},
8907+
"Put /request/method/host": {
8908+
"environments": ["compute", "viceroy"],
8909+
"downstream_request": {
8910+
"method": "Put",
8911+
"pathname": "/request/method/host"
8912+
},
8913+
"downstream_response": {
8914+
"status": 200,
8915+
"body": "",
8916+
"headers": [["result", "PUT"]]
8917+
}
8918+
},
8919+
"DELETE /request/method/host": {
8920+
"environments": ["compute", "viceroy"],
8921+
"downstream_request": {
8922+
"method": "DELETE",
8923+
"pathname": "/request/method/host"
8924+
},
8925+
"downstream_response": {
8926+
"status": 200,
8927+
"body": "",
8928+
"headers": [["result", "DELETE"]]
8929+
}
8930+
},
8931+
"DeLeTe /request/method/host": {
8932+
"environments": ["compute", "viceroy"],
8933+
"downstream_request": {
8934+
"method": "DeLeTe",
8935+
"pathname": "/request/method/host"
8936+
},
8937+
"downstream_response": {
8938+
"status": 200,
8939+
"body": "",
8940+
"headers": [["result", "DELETE"]]
8941+
}
8942+
},
8943+
"delete /request/method/host": {
8944+
"environments": ["compute", "viceroy"],
8945+
"downstream_request": {
8946+
"method": "delete",
8947+
"pathname": "/request/method/host"
8948+
},
8949+
"downstream_response": {
8950+
"status": 200,
8951+
"body": "",
8952+
"headers": [["result", "DELETE"]]
8953+
}
8954+
},
8955+
"HELLO /request/method/host": {
8956+
"environments": ["compute", "viceroy"],
8957+
"downstream_request": {
8958+
"method": "HELLO",
8959+
"pathname": "/request/method/host"
8960+
},
8961+
"downstream_response": {
8962+
"status": 200,
8963+
"body": "",
8964+
"headers": [["result", "HELLO"]]
8965+
}
8966+
},
8967+
"hello /request/method/host": {
8968+
"environments": ["compute", "viceroy"],
8969+
"downstream_request": {
8970+
"method": "hello",
8971+
"pathname": "/request/method/host"
8972+
},
8973+
"downstream_response": {
8974+
"status": 200,
8975+
"body": "",
8976+
"headers": [["result", "hello"]]
8977+
}
8978+
},
8979+
"heLLo /request/method/host": {
8980+
"environments": ["compute", "viceroy"],
8981+
"downstream_request": {
8982+
"method": "heLLo",
8983+
"pathname": "/request/method/host"
8984+
},
8985+
"downstream_response": {
8986+
"status": 200,
8987+
"body": "",
8988+
"headers": [["result", "heLLo"]]
8989+
}
8990+
},
8991+
"!*+-.^_`|~1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ /request/method/host": {
8992+
"environments": ["compute", "viceroy"],
8993+
"downstream_request": {
8994+
"method": "!*+-.^_`|~1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
8995+
"pathname": "/request/method/host"
8996+
},
8997+
"downstream_response": {
8998+
"status": 200,
8999+
"body": "",
9000+
"headers": [["result", "!*+-.^_`|~1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]]
9001+
}
9002+
},
9003+
"GET /request/method/guest": {
9004+
"environments": ["compute", "viceroy"],
9005+
"downstream_request": {
9006+
"method": "GET",
9007+
"pathname": "/request/method/guest"
9008+
},
9009+
"downstream_response": {
9010+
"status": 200,
9011+
"body": "ok"
9012+
}
87389013
}
87399014
}

runtime/fastly/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.27)
22

33
include("../StarlingMonkey/cmake/add_as_subproject.cmake")
44

5-
add_builtin(fastly::runtime SRC handler.cpp common/ip_octets_to_js_string.cpp)
5+
add_builtin(fastly::runtime SRC handler.cpp common/ip_octets_to_js_string.cpp common/normalize_http_method.cpp)
66
add_builtin(fastly::cache_simple SRC builtins/cache-simple.cpp DEPENDENCIES OpenSSL)
77
add_builtin(fastly::fastly SRC builtins/fastly.cpp)
88
add_builtin(fastly::backend SRC builtins/backend.cpp)

runtime/fastly/builtins/fetch-event.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../../StarlingMonkey/builtins/web/url.h"
44
#include "../../StarlingMonkey/builtins/web/worker-location.h"
55
#include "../common/ip_octets_to_js_string.h"
6+
#include "../common/normalize_http_method.h"
67
#include "../host-api/fastly.h"
78
#include "../host-api/host_api_fastly.h"
89
#include "./fetch/request-response.h"
@@ -495,7 +496,8 @@ bool FetchEvent::init_request(JSContext *cx, JS::HandleObject self, host_api::Ht
495496
bool is_head = method_str == "HEAD"sv;
496497

497498
if (!is_get) {
498-
JS::RootedString method(cx, JS_NewStringCopyN(cx, method_str.ptr.release(), method_str.len));
499+
std::ignore = common::normalize_http_method(method_str.begin(), method_str.size());
500+
JS::RootedString method(cx, JS_NewStringCopyN(cx, method_str.begin(), method_str.len));
499501
if (!method) {
500502
return false;
501503
}

0 commit comments

Comments
 (0)