Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/next/src/client/resolve-href.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export function resolveHref(

// repeated slashes and backslashes in the URL are considered
// invalid and will never match a Next.js page/file
const urlProtoMatch = urlAsString.match(/^[a-zA-Z]{1,}:\/\//)
// https://www.rfc-editor.org/rfc/rfc3986.html#section-3.1
const urlProtoMatch = urlAsString.match(/^[a-z][a-z0-9+.-]*:\/\//i)
const urlAsStringNoProto = urlProtoMatch
? urlAsString.slice(urlProtoMatch[0].length)
: urlAsString
Expand Down
14 changes: 14 additions & 0 deletions test/integration/invalid-href/pages/exotic-href.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Link from 'next/link'

export default function Page() {
return (
<>
<Link href="HTTPs://google.com">HTTPs</Link>
<Link href="flatpak+https://dl.flathub.org/repo/appstream/net.krafting.Playlifin.flatpakref">
flatpak+https
</Link>
<Link href="com.apple.tv://">com.apple.tv</Link>
<Link href="itms-apps://">itms-apps</Link>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a typo. Apple App Store really uses itms-apps

</>
)
}
6 changes: 3 additions & 3 deletions test/integration/invalid-href/pages/second.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ export default function Page() {
id="click-me"
onClick={(e) => {
e.preventDefault()
// this should throw an error on load since prefetch
// receives the invalid href
router[method](invalidLink)
}}
>
invalid link :o
</a>
) : (
// this should throw an error on load since prefetch
// receives the invalid href
<Link href={invalidLink} id="click-me">
invalid link :o
valid link :o
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was changed a long time ago.

</Link>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import cheerio from 'cheerio'
import webdriver from 'next-webdriver'
import { join } from 'path'

let app
let appPort
let app: Awaited<ReturnType<typeof nextStart>>
let appPort: number
const appDir = join(__dirname, '..')

// This test doesn't seem to benefit from retries, let's disable them until the test gets fixed
Expand Down Expand Up @@ -98,10 +98,18 @@ describe('Invalid hrefs', () => {
await noError('/first')
})

it('does not show error in production when https://google.com is used as href on Link', async () => {
it('does not show error in production when https:// is used in href on Link', async () => {
await noError('/second')
})

it('does not show error in production when exotic protocols are used in href in Link', async () => {
const browser = await webdriver(appPort, '/exotic-href')

expect(
(await browser.log()).filter((x) => x.source === 'error')
).toEqual([])
})

it('does not show error when internal href is used with external as', async () => {
await noError('/invalid-relative', true)
})
Expand Down Expand Up @@ -160,10 +168,18 @@ describe('Invalid hrefs', () => {
await noError('/first')
})

it('does not show error when https://google.com is used as href on Link', async () => {
it('does not show error when https:// is used as href in Link', async () => {
await noError('/second')
})

it('does not show error when exotic protocols are used in href in Link', async () => {
const browser = await webdriver(appPort, '/exotic-href')

expect(
(await browser.log()).filter((x) => x.source === 'error')
).toEqual([])
})

// eslint-disable-next-line jest/no-identical-title
it('shows error when dynamic route mismatch is used on Link', async () => {
await showsError(
Expand Down
Loading