Skip to content

Commit

Permalink
Bug fix: dynamic page should not be interpreted as predefined page (v…
Browse files Browse the repository at this point in the history
…ercel#33808)

Fixes: vercel#17096
Fixes: vercel#23824
Closes: vercel#33765

## Bug

- [x] Related issues linked using `fixes #number`
- [x] Integration tests added in vercel#33765
- [x] Errors have helpful link attached (N/A)

Co-authored-by: Tim Neutkens <6324199+timneutkens@users.noreply.github.com>
Co-authored-by: JJ Kasper <22380829+ijjk@users.noreply.github.com>
  • Loading branch information
3 people authored and natew committed Feb 16, 2022
1 parent 13794d2 commit be1397a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 9 deletions.
22 changes: 13 additions & 9 deletions packages/next/server/base-server.ts
Expand Up @@ -881,7 +881,7 @@ export default abstract class Server {
): Promise<boolean> {
let page = pathname
let params: Params | false = false
let pageFound = await this.hasPage(page)
let pageFound = !isDynamicRoute(page) && (await this.hasPage(page))

if (!pageFound && this.dynamicRoutes) {
for (const dynamicRoute of this.dynamicRoutes) {
Expand Down Expand Up @@ -1536,15 +1536,19 @@ export default abstract class Server {
delete query._nextBubbleNoFallback

try {
const result = await this.findPageComponents(pathname, query)
if (result) {
try {
return await this.renderToResponseWithComponents(ctx, result)
} catch (err) {
const isNoFallbackError = err instanceof NoFallbackError
// Ensure a request to the URL /accounts/[id] will be treated as a dynamic
// route correctly and not loaded immediately without parsing params.
if (!isDynamicRoute(pathname)) {
const result = await this.findPageComponents(pathname, query)
if (result) {
try {
return await this.renderToResponseWithComponents(ctx, result)
} catch (err) {
const isNoFallbackError = err instanceof NoFallbackError

if (!isNoFallbackError || (isNoFallbackError && bubbleNoFallback)) {
throw err
if (!isNoFallbackError || (isNoFallbackError && bubbleNoFallback)) {
throw err
}
}
}
}
Expand Down
63 changes: 63 additions & 0 deletions test/e2e/dynamic-route-interpolation/index.test.ts
@@ -0,0 +1,63 @@
import { createNext } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { renderViaHTTP } from 'next-test-utils'
import cheerio from 'cheerio'

describe('Dynamic Route Interpolation', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: {
'pages/blog/[slug].js': `
export function getServerSideProps({ params }) {
return { props: { slug: params.slug } }
}
export default function Page(props) {
return <p id="slug">{props.slug}</p>
}
`,

'pages/api/dynamic/[slug].js': `
export default function Page(req, res) {
const { slug } = req.query
res.end('slug: ' + slug)
}
`,
},
dependencies: {},
})
})
afterAll(() => next.destroy())

it('should work', async () => {
const html = await renderViaHTTP(next.url, '/blog/a')
const $ = cheerio.load(html)
expect($('#slug').text()).toBe('a')
})

it('should work with parameter itself', async () => {
const html = await renderViaHTTP(next.url, '/blog/[slug]')
const $ = cheerio.load(html)
expect($('#slug').text()).toBe('[slug]')
})

it('should work with brackets', async () => {
const html = await renderViaHTTP(next.url, '/blog/[abc]')
const $ = cheerio.load(html)
expect($('#slug').text()).toBe('[abc]')
})

it('should work with parameter itself in API routes', async () => {
const text = await renderViaHTTP(next.url, '/api/dynamic/[slug]')
expect(text).toBe('slug: [slug]')
})

it('should work with brackets in API routes', async () => {
const text = await renderViaHTTP(next.url, '/api/dynamic/[abc]')
expect(text).toBe('slug: [abc]')
})
})

0 comments on commit be1397a

Please sign in to comment.