Skip to content

Commit

Permalink
fix: Encode special characters in keys (#600)
Browse files Browse the repository at this point in the history
* fix: Encode special characters in keys

Closes #599.

* test: Start with less encoding to verify first parsing
  • Loading branch information
franky47 authored Aug 8, 2024
1 parent de50388 commit 905edc9
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 1 deletion.
18 changes: 18 additions & 0 deletions packages/e2e/cypress/e2e/repro-599.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// <reference types="cypress" />

it('Reproduction for issue #599', () => {
// Start without encoding for most characters
cy.visit(
'/app/repro-599?a %26b%3Fc%3Dd%23e%f%2Bg"h\'i`j<k>l(m)n*o,p.q:r;s/t=init'
)
cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
cy.get('input').should('have.value', 'init')
cy.get('p').should('have.text', 'init')
cy.get('button').click()
cy.get('input').should('have.value', 'works')
cy.get('p').should('have.text', 'works')
cy.location('search').should(
'eq',
'?a%20%26b%3Fc%3Dd%23e%f%2Bg%22h%27i`j%3Ck%3El(m)n*o,p.q:r;s/t=works'
)
})
27 changes: 27 additions & 0 deletions packages/e2e/src/app/app/repro-599/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use client'

import { parseAsString, useQueryState, useQueryStates } from 'nuqs'
import { Suspense } from 'react'

export default function Page() {
return (
<Suspense>
<Client />
</Suspense>
)
}

const key = 'a &b?c=d#e%f+g"h\'i`j<k>l(m)n*o,p.q:r;s/t'
const parser = parseAsString.withDefault('')

function Client() {
const [a, setValue] = useQueryState(key, parser)
const [{ [key]: b }] = useQueryStates({ [key]: parser })
return (
<>
<input value={a} onChange={e => setValue(e.target.value)} />
<p>{b}</p>
<button onClick={() => setValue('works')}>Test</button>
</>
)
}
7 changes: 7 additions & 0 deletions packages/nuqs/src/url-encoding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ describe('url-encoding/renderQueryString', () => {
expect(search).toBe(url.search)
}
})
test('keys with special characters get escaped', () => {
const search = new URLSearchParams()
search.set('a &b?c=d#e%f+g"h\'i`j<k>l(m)n*o,p.q:r;s/t', 'value')
expect(renderQueryString(search)).toBe(
'?a %26b%3Fc%3Dd%23e%f%2Bg"h\'i`j<k>l(m)n*o,p.q:r;s/t=value'
)
})
})

test.skip('encodeURI vs encodeURIComponent vs custom encoding', () => {
Expand Down
10 changes: 9 additions & 1 deletion packages/nuqs/src/url-encoding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ export function renderQueryString(search: URLSearchParams) {
}
const query: string[] = []
for (const [key, value] of search.entries()) {
query.push(`${key}=${encodeQueryValue(value)}`)
// Replace disallowed characters in keys,
// see https://github.com/47ng/nuqs/issues/599
const safeKey = key
.replace(/#/g, '%23')
.replace(/&/g, '%26')
.replace(/\+/g, '%2B')
.replace(/=/g, '%3D')
.replace(/\?/g, '%3F')
query.push(`${safeKey}=${encodeQueryValue(value)}`)
}
return '?' + query.join('&')
}
Expand Down

0 comments on commit 905edc9

Please sign in to comment.