diff --git a/templates/src/client/app.ts b/templates/src/client/app.ts index ed46630..0a27ee7 100644 --- a/templates/src/client/app.ts +++ b/templates/src/client/app.ts @@ -87,11 +87,14 @@ export function select_route(url: URL): Target { const match = page.pattern.exec(path); if (match) { - const query: Record = {}; + const query: Record = Object.create(null); if (url.search.length > 0) { url.search.slice(1).split('&').forEach(searchParam => { - const [, key, value] = /([^=]*)(?:=(.*))?/.exec(searchParam); - query[decodeURIComponent(key)] = decodeURIComponent((value || '').replace(/\+/g, ' ')); + let [, key, value] = /([^=]*)(?:=(.*))?/.exec(decodeURIComponent(searchParam)); + value = (value || '').replace(/\+/g, ' '); + if (typeof query[key] === 'string') query[key] = [query[key]]; + if (typeof query[key] === 'object') query[key].push(value); + else query[key] = value; }); } return { url, path, page, match, query }; diff --git a/templates/src/client/types.ts b/templates/src/client/types.ts index 08e7a04..2a28582 100644 --- a/templates/src/client/types.ts +++ b/templates/src/client/types.ts @@ -55,7 +55,7 @@ export type Target = { path: string; page: Page; match: RegExpExecArray; - query: Record; + query: Record; }; export type Redirect = { diff --git a/test/apps/basics/src/routes/echo-query/index.html b/test/apps/basics/src/routes/echo-query/index.html index 17230c1..aa09b35 100644 --- a/test/apps/basics/src/routes/echo-query/index.html +++ b/test/apps/basics/src/routes/echo-query/index.html @@ -1,9 +1 @@ -

message: "{message}"

- - \ No newline at end of file +

{JSON.stringify(query)}

\ No newline at end of file diff --git a/test/apps/basics/src/routes/index.html b/test/apps/basics/src/routes/index.html index 221c0f5..b61b244 100644 --- a/test/apps/basics/src/routes/index.html +++ b/test/apps/basics/src/routes/index.html @@ -3,5 +3,6 @@ a ok ok +ok
\ No newline at end of file diff --git a/test/apps/basics/test.ts b/test/apps/basics/test.ts index 7190fd9..f7e1ac9 100644 --- a/test/apps/basics/test.ts +++ b/test/apps/basics/test.ts @@ -204,7 +204,7 @@ describe('basics', function() { assert.equal( await title(), - 'message: ""' + '{"message":""}' ); }); @@ -217,7 +217,29 @@ describe('basics', function() { assert.equal( await title(), - 'message: ""' + '{"message":""}' + ); + }); + + it('accepts duplicated query string parameter on server', async () => { + await page.goto(`${base}/echo-query?p=one&p=two`); + + assert.equal( + await title(), + '{"p":["one","two"]}' + ); + }); + + it('accepts duplicated query string parameter on client', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('a[href="echo-query?p=one&p=two"]') + + assert.equal( + await title(), + '{"p":["one","two"]}' ); });