Skip to content

Commit 73cdc27

Browse files
Jake ChampionJakeChampion
authored andcommitted
fix: When converting a URL to a string, do not add a ? if there are no query string parameters
fixes #484
1 parent 5cc1cd6 commit 73cdc27

File tree

7 files changed

+85
-8
lines changed

7 files changed

+85
-8
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ jobs:
239239
- streaming-close
240240
- tee
241241
- timers
242+
- urlsearchparams
242243
steps:
243244
- name: Checkout fastly/js-compute-runtime
244245
uses: actions/checkout@v3
@@ -378,6 +379,7 @@ jobs:
378379
- 'secret-store'
379380
- 'status'
380381
- 'timers'
382+
- 'urlsearchparams'
381383
steps:
382384
- uses: actions/checkout@v3
383385
with:

c-dependencies/js-compute-runtime/rust-url/src/lib.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,23 @@ impl JSUrlSearchParams {
3636
match self.url_or_str {
3737
UrlOrString::Url(url) => {
3838
let url = unsafe { url.as_mut().unwrap() };
39-
let mut pairs = url.url.query_pairs_mut();
40-
pairs.clear().extend_pairs(self.list.iter());
39+
if self.list.is_empty() {
40+
url.url.set_query(None);
41+
} else {
42+
let mut pairs = url.url.query_pairs_mut();
43+
pairs.clear();
44+
pairs.extend_pairs(self.list.iter());
45+
}
4146
}
4247
UrlOrString::Str(_) => {
43-
let str = form_urlencoded::Serializer::new(String::new())
44-
.extend_pairs(&*self.list)
45-
.finish();
48+
let str;
49+
if self.list.is_empty() {
50+
str = form_urlencoded::Serializer::new(String::new()).finish();
51+
} else {
52+
str = form_urlencoded::Serializer::new(String::new())
53+
.extend_pairs(&*self.list)
54+
.finish();
55+
}
4656
self.url_or_str = UrlOrString::Str(str);
4757
}
4858
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint-env serviceworker */
2+
/* global ReadableStream ObjectStore ObjectStoreEntry */
3+
import { env } from 'fastly:env';
4+
import { pass, fail, assert, assertThrows, assertRejects, assertResolves } from "../../../assertions.js";
5+
6+
addEventListener("fetch", event => {
7+
event.respondWith(app(event))
8+
})
9+
/**
10+
* @param {FetchEvent} event
11+
* @returns {Response}
12+
*/
13+
async function app(event) {
14+
try {
15+
const path = (new URL(event.request.url)).pathname;
16+
console.log(`path: ${path}`)
17+
console.log(`FASTLY_SERVICE_VERSION: ${env('FASTLY_SERVICE_VERSION')}`)
18+
if (routes.has(path)) {
19+
const routeHandler = routes.get(path);
20+
return await routeHandler()
21+
}
22+
return fail(`${path} endpoint does not exist`)
23+
} catch (error) {
24+
return fail(`The routeHandler threw an error: ${error.message}` + '\n' + error.stack)
25+
}
26+
}
27+
28+
const routes = new Map();
29+
routes.set('/', () => {
30+
routes.delete('/');
31+
let test_routes = Array.from(routes.keys())
32+
return new Response(JSON.stringify(test_routes), { 'headers': { 'content-type': 'application/json' } });
33+
});
34+
35+
routes.set("/urlsearchparams/sort", async () => {
36+
const urlObj = new URL('http://www.example.com');
37+
urlObj.searchParams.sort();
38+
let error = assert(urlObj.toString(), 'http://www.example.com/', `urlObj.toString()`)
39+
if (error) { return error }
40+
return pass()
41+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This file describes a Fastly Compute@Edge package. To learn more visit:
2+
# https://developer.fastly.com/reference/fastly-toml/
3+
4+
authors = ["[email protected]"]
5+
description = ""
6+
language = "other"
7+
manifest_version = 2
8+
name = "urlsearchparams"
9+
service_id = ""
10+
11+
[scripts]
12+
build = "node ../../../../js-compute-runtime-cli.js"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"GET /urlsearchparams/sort": {
3+
"environments": ["c@e", "viceroy"],
4+
"downstream_request": {
5+
"method": "GET",
6+
"pathname": "/urlsearchparams/sort"
7+
},
8+
"downstream_response": {
9+
"status": 200
10+
}
11+
}
12+
}

tests/wpt-harness/expectations/url/urlsearchparams-delete.any.js.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
"status": "PASS"
77
},
88
"Deleting all params removes ? from URL": {
9-
"status": "FAIL"
9+
"status": "PASS"
1010
},
1111
"Removing non-existent param removes ? from URL": {
12-
"status": "FAIL"
12+
"status": "PASS"
1313
}
1414
}

tests/wpt-harness/expectations/url/urlsearchparams-sort.any.js.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@
4848
"status": "PASS"
4949
},
5050
"Sorting non-existent params removes ? from URL": {
51-
"status": "FAIL"
51+
"status": "PASS"
5252
}
5353
}

0 commit comments

Comments
 (0)