Skip to content

Commit c2a39d6

Browse files
committed
fix: trim whitespace in redirect from and to
Redirects silently failed to match when a leading/trailing space was present in the address (e.g. `to = " https://example.com"`), which is a common typo that is hard to spot. Trimming the values in the redirect normalizer resolves the issue while preserving the parsed rule shape. Fixes #4707
1 parent 85c0113 commit c2a39d6

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

src/utils/redirects.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ const getErrorMessage = function ({ message }) {
3636
// - `from` is called `origin`
3737
// - `query` is called `params`
3838
// - `conditions.role|country|language` are capitalized
39+
// Leading and trailing whitespace in `from` and `to` is trimmed so that typos
40+
// such as `to = " https://example.com"` do not silently break redirects
41+
// (see https://github.com/netlify/cli/issues/4707).
42+
const trimValue = (value) => (typeof value === 'string' ? value.trim() : value)
43+
3944
const normalizeRedirect = function ({
4045
// @ts-expect-error TS(7031) FIXME: Binding element 'country' implicitly has an 'any' ... Remove this comment to see the full error message
4146
conditions: { country, language, role, ...conditions },
@@ -45,11 +50,15 @@ const normalizeRedirect = function ({
4550
query,
4651
// @ts-expect-error TS(7031) FIXME: Binding element 'signed' implicitly has an 'any' t... Remove this comment to see the full error message
4752
signed,
53+
// @ts-expect-error TS(7031) FIXME: Binding element 'to' implicitly has an 'any type...
54+
to,
4855
...redirect
4956
}) {
5057
return {
5158
...redirect,
52-
origin: from,
59+
origin: trimValue(from),
60+
path: trimValue(from),
61+
to: trimValue(to),
5362
params: query,
5463
conditions: {
5564
...conditions,

tests/unit/utils/redirects.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,29 @@ test('should parse redirect rules from _redirects file and netlify.toml', async
230230
expect(redirects).toEqual(expected)
231231
})
232232
})
233+
234+
test('should trim leading and trailing whitespace from redirect `from` and `to`', async (t) => {
235+
await withSiteBuilder(t, async (builder) => {
236+
await builder
237+
.withNetlifyToml({
238+
config: {
239+
redirects: [
240+
{
241+
from: ' /leading-space ',
242+
status: 200,
243+
to: ' https://www.netlify.com ',
244+
},
245+
],
246+
},
247+
})
248+
.build()
249+
250+
// @ts-expect-error TS(2345) FIXME: Argument of type '{ configPath: string; }' is not ... Remove this comment to see the full error message
251+
const redirects = await parseRedirects({ configPath: `${builder.directory}/netlify.toml` })
252+
expect(redirects[0]).toMatchObject({
253+
origin: '/leading-space',
254+
path: '/leading-space',
255+
to: 'https://www.netlify.com',
256+
})
257+
})
258+
})

0 commit comments

Comments
 (0)