diff --git a/src/cypress/integration/basePath_spec.js b/src/cypress/integration/basePath_spec.js index 9759dd5ba3..00a3c014bf 100644 --- a/src/cypress/integration/basePath_spec.js +++ b/src/cypress/integration/basePath_spec.js @@ -74,18 +74,30 @@ describe('getInitialProps', () => { cy.get('ul').first().children().should('have.length', 5) }) + + it('loads TV shows w basePath', () => { + cy.visit('/foo') + + cy.get('ul').first().children().should('have.length', 5) + }) + + it('loads TV shows when SSR-ing w basePath', () => { + cy.ssr('/foo') + + cy.get('ul').first().children().should('have.length', 5) + }) }) context('with dynamic route', () => { it('loads TV show', () => { - cy.visit('/shows/24251') + cy.visit('/foo/shows/24251') cy.get('h1').should('contain', 'Show #24251') cy.get('p').should('contain', 'Animal Science') }) it('loads TV show when SSR-ing', () => { - cy.ssr('/shows/24251') + cy.ssr('/foo/shows/24251') cy.get('h1').should('contain', 'Show #24251') cy.get('p').should('contain', 'Animal Science') @@ -94,7 +106,7 @@ describe('getInitialProps', () => { context('with catch-all route', () => { it('displays all URL parameters, including query string parameters', () => { - cy.visit('/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat') + cy.visit('/foo/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat') // path parameters cy.get('p').should('contain', '[0]: 94') @@ -112,7 +124,7 @@ describe('getInitialProps', () => { }) it('displays all URL parameters when SSR-ing, including query string parameters', () => { - cy.visit('/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat') + cy.visit('/foo/shows/94/this-is-all/being/captured/yay?search=dog&custom-param=cat') // path parameters cy.get('p').should('contain', '[0]: 94') @@ -159,21 +171,21 @@ describe('getServerSideProps', () => { context('with static route', () => { it('loads TV shows', () => { - cy.visit('/getServerSideProps/static') + cy.visit('/foo/getServerSideProps/static') cy.get('h1').should('contain', 'Show #42') cy.get('p').should('contain', 'Sleepy Hollow') }) it('loads TV shows when SSR-ing', () => { - cy.ssr('/getServerSideProps/static') + cy.ssr('/foo/getServerSideProps/static') cy.get('h1').should('contain', 'Show #42') cy.get('p').should('contain', 'Sleepy Hollow') }) it('loads page props from data .json file when navigating to it', () => { - cy.visit('/') + cy.visit('/foo') cy.window().then((w) => (w.noReload = true)) // Navigate to page and test that no reload is performed @@ -187,14 +199,14 @@ describe('getServerSideProps', () => { context('with dynamic route', () => { it('loads TV show', () => { - cy.visit('/getServerSideProps/1337') + cy.visit('/foo/getServerSideProps/1337') cy.get('h1').should('contain', 'Show #1337') cy.get('p').should('contain', 'Whodunnit?') }) it('loads TV show when SSR-ing', () => { - cy.ssr('/getServerSideProps/1337') + cy.ssr('/foo/getServerSideProps/1337') cy.get('h1').should('contain', 'Show #1337') cy.get('p').should('contain', 'Whodunnit?') @@ -224,7 +236,7 @@ describe('getServerSideProps', () => { context('with catch-all route', () => { it('does not match base path (without params)', () => { cy.request({ - url: '/getServerSideProps/catch/all', + url: '/foo/getServerSideProps/catch/all', failOnStatusCode: false, }).then((response) => { expect(response.status).to.eq(404) @@ -235,14 +247,14 @@ describe('getServerSideProps', () => { }) it('loads TV show with one param', () => { - cy.visit('/getServerSideProps/catch/all/1337') + cy.visit('/foo/getServerSideProps/catch/all/1337') cy.get('h1').should('contain', 'Show #1337') cy.get('p').should('contain', 'Whodunnit?') }) it('loads TV show with multiple params', () => { - cy.visit('/getServerSideProps/catch/all/1337/multiple/params') + cy.visit('/foo/getServerSideProps/catch/all/1337/multiple/params') cy.get('h1').should('contain', 'Show #1337') cy.get('p').should('contain', 'Whodunnit?') @@ -273,14 +285,14 @@ describe('getServerSideProps', () => { describe('getStaticProps', () => { context('with static route', () => { it('loads TV show', () => { - cy.visit('/getStaticProps/static') + cy.visit('/foo/getStaticProps/static') cy.get('h1').should('contain', 'Show #71') cy.get('p').should('contain', 'Dancing with the Stars') }) it('loads page props from data .json file when navigating to it', () => { - cy.visit('/') + cy.visit('/foo') cy.window().then((w) => (w.noReload = true)) // Navigate to page and test that no reload is performed @@ -293,14 +305,14 @@ describe('getStaticProps', () => { context('with revalidate', () => { it('loads TV show', () => { - cy.visit('/getStaticProps/with-revalidate') + cy.visit('/foo/getStaticProps/with-revalidate') cy.get('h1').should('contain', 'Show #71') cy.get('p').should('contain', 'Dancing with the Stars') }) it('loads TV shows when SSR-ing', () => { - cy.ssr('/getStaticProps/with-revalidate') + cy.ssr('/foo/getStaticProps/with-revalidate') cy.get('h1').should('contain', 'Show #71') cy.get('p').should('contain', 'Dancing with the Stars') @@ -311,17 +323,17 @@ describe('getStaticProps', () => { context('with dynamic route', () => { context('without fallback', () => { it('loads shows 1 and 2', () => { - cy.visit('/getStaticProps/1') + cy.visit('/foo/getStaticProps/1') cy.get('h1').should('contain', 'Show #1') cy.get('p').should('contain', 'Under the Dome') - cy.visit('/getStaticProps/2') + cy.visit('/foo/getStaticProps/2') cy.get('h1').should('contain', 'Show #2') cy.get('p').should('contain', 'Person of Interest') }) it('loads page props from data .json file when navigating to it', () => { - cy.visit('/') + cy.visit('/foo') cy.window().then((w) => (w.noReload = true)) // Navigate to page and test that no reload is performed @@ -342,7 +354,7 @@ describe('getStaticProps', () => { it('returns 404 when trying to access non-defined path', () => { cy.request({ - url: '/getStaticProps/3', + url: '/foo/getStaticProps/3', failOnStatusCode: false, }).then((response) => { expect(response.status).to.eq(404) @@ -355,31 +367,31 @@ describe('getStaticProps', () => { context('with fallback', () => { it('loads pre-rendered TV shows 3 and 4', () => { - cy.visit('/getStaticProps/withFallback/3') + cy.visit('/foo/getStaticProps/withFallback/3') cy.get('h1').should('contain', 'Show #3') cy.get('p').should('contain', 'Bitten') - cy.visit('/getStaticProps/withFallback/4') + cy.visit('/foo/getStaticProps/withFallback/4') cy.get('h1').should('contain', 'Show #4') cy.get('p').should('contain', 'Arrow') }) it('loads non-pre-rendered TV show', () => { - cy.visit('/getStaticProps/withFallback/75') + cy.visit('/foo/getStaticProps/withFallback/75') cy.get('h1').should('contain', 'Show #75') cy.get('p').should('contain', 'The Mindy Project') }) it('loads non-pre-rendered TV shows when SSR-ing', () => { - cy.ssr('/getStaticProps/withFallback/75') + cy.ssr('/foo/getStaticProps/withFallback/75') cy.get('h1').should('contain', 'Show #75') cy.get('p').should('contain', 'The Mindy Project') }) it('loads page props from data .json file when navigating to it', () => { - cy.visit('/') + cy.visit('/foo') cy.window().then((w) => (w.noReload = true)) // Navigate to page and test that no reload is performed @@ -407,14 +419,14 @@ describe('getStaticProps', () => { context('with revalidate', () => { it('loads TV show', () => { - cy.visit('/getStaticProps/withRevalidate/75') + cy.visit('/foo/getStaticProps/withRevalidate/75') cy.get('h1').should('contain', 'Show #75') cy.get('p').should('contain', 'The Mindy Project') }) it('loads TV shows when SSR-ing', () => { - cy.ssr('/getStaticProps/withRevalidate/75') + cy.ssr('/foo/getStaticProps/withRevalidate/75') cy.get('h1').should('contain', 'Show #75') cy.get('p').should('contain', 'The Mindy Project') @@ -445,17 +457,17 @@ describe('getStaticProps', () => { context('with catch-all route', () => { context('with fallback', () => { it('loads pre-rendered shows 1 and 2', () => { - cy.visit('/getStaticProps/withFallback/my/path/1') + cy.visit('/foo/getStaticProps/withFallback/my/path/1') cy.get('h1').should('contain', 'Show #1') cy.get('p').should('contain', 'Under the Dome') - cy.visit('/getStaticProps/withFallback/my/path/2') + cy.visit('/foo/getStaticProps/withFallback/my/path/2') cy.get('h1').should('contain', 'Show #2') cy.get('p').should('contain', 'Person of Interest') }) it('loads non-pre-rendered TV show', () => { - cy.visit('/getStaticProps/withFallback/undefined/catch/all/path/75') + cy.visit('/foo/getStaticProps/withFallback/undefined/catch/all/path/75') cy.get('h1').should('contain', 'Show #75') cy.get('p').should('contain', 'The Mindy Project') @@ -493,7 +505,7 @@ describe('getStaticProps', () => { describe('API endpoint', () => { context('with static route', () => { it('returns hello world, with all response headers', () => { - cy.request('/api/static').then((response) => { + cy.request('/foo/api/static').then((response) => { expect(response.headers['content-type']).to.include('application/json') expect(response.headers['my-custom-header']).to.include('header123') @@ -504,7 +516,7 @@ describe('API endpoint', () => { context('with dynamic route', () => { it('returns TV show', () => { - cy.request('/api/shows/305').then((response) => { + cy.request('/foo/api/shows/305').then((response) => { expect(response.headers['content-type']).to.include('application/json') expect(response.body).to.have.property('show') @@ -516,7 +528,7 @@ describe('API endpoint', () => { context('with catch-all route', () => { it('returns all URL paremeters, including query string parameters', () => { - cy.request('/api/shows/590/this/path/is/captured?metric=dog&p2=cat').then((response) => { + cy.request('/foo/api/shows/590/this/path/is/captured?metric=dog&p2=cat').then((response) => { expect(response.headers['content-type']).to.include('application/json') // Params @@ -539,7 +551,7 @@ describe('API endpoint', () => { }) it('redirects with res.redirect', () => { - cy.visit('/api/redirect?to=999') + cy.visit('/foo/api/redirect?to=999') cy.url().should('include', '/shows/999') cy.get('h1').should('contain', 'Show #999') @@ -547,7 +559,7 @@ describe('API endpoint', () => { }) it('exposes function context on the req object', () => { - cy.request('/api/context').then((response) => { + cy.request('/foo/api/context').then((response) => { const { req: { netlifyFunctionParams: { event, context }, @@ -570,13 +582,13 @@ describe('API endpoint', () => { describe('Preview Mode', () => { it('redirects to preview test page with dynamic route', () => { - cy.visit('/api/enterPreview?id=999') + cy.visit('/foo/api/enterPreview?id=999') cy.url().should('include', '/previewTest/999') }) it('redirects to static preview test page', () => { - cy.visit('/api/enterPreviewStatic') + cy.visit('/foo/api/enterPreviewStatic') cy.url().should('include', '/previewTest/static') }) @@ -604,7 +616,7 @@ describe('Preview Mode', () => { }) it('renders serverSideProps page in preview mode', () => { - cy.visit('/api/enterPreview?id=999') + cy.visit('/foo/api/enterPreview?id=999') if (Cypress.env('DEPLOY') === 'local') { cy.makeCookiesWorkWithHttpAndReload() @@ -617,13 +629,13 @@ describe('Preview Mode', () => { it('renders staticProps page in preview mode', () => { // cypress local (aka netlify dev) doesn't support cookie-based redirects if (Cypress.env('DEPLOY') !== 'local') { - cy.visit('/api/enterPreviewStatic') + cy.visit('/foo/api/enterPreviewStatic') cy.get('h1').should('contain', 'Number: 3') } }) it('can move in and out of preview mode for SSRed page', () => { - cy.visit('/api/enterPreview?id=999') + cy.visit('/foo/api/enterPreview?id=999') if (Cypress.env('DEPLOY') === 'local') { cy.makeCookiesWorkWithHttpAndReload() @@ -640,7 +652,7 @@ describe('Preview Mode', () => { cy.get('p').should('contain', 'Corey Lof') // Exit preview mode - cy.visit('/api/exitPreview') + cy.visit('/foo/api/exitPreview') // Verify that we're no longer in preview mode cy.contains('previewTest/222').click() @@ -650,7 +662,7 @@ describe('Preview Mode', () => { it('can move in and out of preview mode for static page', () => { if (Cypress.env('DEPLOY') !== 'local') { - cy.visit('/api/enterPreviewStatic') + cy.visit('/foo/api/enterPreviewStatic') cy.window().then((w) => (w.noReload = true)) cy.get('h1').should('contain', 'Number: 3') @@ -664,7 +676,7 @@ describe('Preview Mode', () => { cy.window().should('have.property', 'noReload', true) // Exit preview mode - cy.visit('/api/exitPreview') + cy.visit('/foo/api/exitPreview') // TO-DO: test if this is the static html? // Verify that we're no longer in preview mode @@ -675,13 +687,13 @@ describe('Preview Mode', () => { it('hits the prerendered html out of preview mode and netlify function in preview mode', () => { if (Cypress.env('DEPLOY') !== 'local') { - cy.request('/previewTest/static').then((response) => { + cy.request('/foo/previewTest/static').then((response) => { expect(response.headers['cache-control']).to.include('public') }) - cy.visit('/api/enterPreviewStatic') + cy.visit('/foo/api/enterPreviewStatic') - cy.request('/previewTest/static').then((response) => { + cy.request('/foo/previewTest/static').then((response) => { expect(response.headers['cache-control']).to.include('private') }) } @@ -691,13 +703,13 @@ describe('Preview Mode', () => { describe('pre-rendered HTML pages', () => { context('with static route', () => { it('renders', () => { - cy.visit('/static') + cy.visit('/foo/static') cy.get('p').should('contain', 'It is a static page.') }) it('renders when SSR-ing', () => { - cy.visit('/static') + cy.visit('/foo/static') cy.get('p').should('contain', 'It is a static page.') }) @@ -705,14 +717,14 @@ describe('pre-rendered HTML pages', () => { context('with dynamic route', () => { it('renders', () => { - cy.visit('/static/superdynamic') + cy.visit('/foo/static/superdynamic') cy.get('p').should('contain', 'It is a static page.') cy.get('p').should('contain', 'it has a dynamic URL parameter: /static/:id.') }) it('renders when SSR-ing', () => { - cy.visit('/static/superdynamic') + cy.visit('/foo/static/superdynamic') cy.get('p').should('contain', 'It is a static page.') cy.get('p').should('contain', 'it has a dynamic URL parameter: /static/:id.') @@ -723,7 +735,7 @@ describe('pre-rendered HTML pages', () => { describe('404 page', () => { it('renders', () => { cy.request({ - url: '/this-page-does-not-exist', + url: '/foo/this-page-does-not-exist', failOnStatusCode: false, }).then((response) => { expect(response.status).to.eq(404) diff --git a/src/lib/helpers/convertToBasePathRedirects.js b/src/lib/helpers/convertToBasePathRedirects.js index ad4cf692a0..e154bb8f53 100644 --- a/src/lib/helpers/convertToBasePathRedirects.js +++ b/src/lib/helpers/convertToBasePathRedirects.js @@ -1,14 +1,10 @@ // This helper converts the collection of redirects for all page types into // the necessary redirects for a basePath-generated site -// i.e. -// no basePath: -// /ssr /.netlify/functions/next_ssr 200 -// with basePath configured: -// /ssr /base/ssr 301! -// /base/ssr /.netlify/functions/next_ssr 200 +// NOTE: /withoutProps/redirects.js has some of its own contained basePath logic const getBasePathDefaultRedirects = ({ basePath, nextRedirects }) => { if (basePath === '') return [] + // In a basePath-configured site, all _next assets are fetched with the prepended basePath return [ { route: `${basePath}/_next/*`, @@ -24,6 +20,7 @@ const convertToBasePathRedirects = ({ basePath, nextRedirects }) => { const basePathRedirects = getBasePathDefaultRedirects({ basePath, nextRedirects }) nextRedirects.forEach((r) => { if (r.route === '/') { + // On Vercel, a basePath configured site 404s on /, but we can ensure it redirects to /basePath const indexRedirects = [ { route: '/', @@ -38,13 +35,21 @@ const convertToBasePathRedirects = ({ basePath, nextRedirects }) => { ] basePathRedirects.push(...indexRedirects) } else if (!r.route.includes('_next/') && r.target.includes('/.netlify/functions') && r.conditions) { - // If preview mode redirect + // If this is a preview mode redirect, we need different behavior than other function targets below + // because the conditions prevent us from doing a route -> basePath/route force basePathRedirects.push({ route: `${basePath}${r.route}`, target: r.target, + force: true, conditions: r.conditions, }) + basePathRedirects.push({ + route: `${basePath}${r.route}`, + target: r.route, + }) } else if (!r.route.includes('_next/') && r.target.includes('/.netlify/functions')) { + // This force redirect is necessary for non-preview mode function targets because the serverless lambdas + // try to strip basePath and redirect to the plain route per https://github.com/vercel/next.js/blob/5bff9eac084b69affe3560c4f4cfd96724aa5e49/packages/next/next-server/lib/router/router.ts#L974 const functionRedirects = [ { route: r.route, diff --git a/src/lib/helpers/formatRedirectTarget.js b/src/lib/helpers/formatRedirectTarget.js new file mode 100644 index 0000000000..ed8d3c7c09 --- /dev/null +++ b/src/lib/helpers/formatRedirectTarget.js @@ -0,0 +1,9 @@ +// Returns formatted redirect target +const { DYNAMIC_PARAMETER_REGEX } = require('../constants/regex') + +const formatRedirectTarget = ({ basePath, target }) => + basePath !== '' && target.includes(basePath) + ? target.replace(DYNAMIC_PARAMETER_REGEX, '/:$1').replace('[', '').replace(']', '').replace('...', '') + : target + +module.exports = formatRedirectTarget diff --git a/src/lib/pages/withoutProps/redirects.js b/src/lib/pages/withoutProps/redirects.js index f48ba3ad58..b85eafb6b3 100644 --- a/src/lib/pages/withoutProps/redirects.js +++ b/src/lib/pages/withoutProps/redirects.js @@ -1,3 +1,4 @@ +const getNextConfig = require('../../../../helpers/getNextConfig') const addDefaultLocaleRedirect = require('../../helpers/addDefaultLocaleRedirect') const asyncForEach = require('../../helpers/asyncForEach') const isDynamicRoute = require('../../helpers/isDynamicRoute') @@ -20,12 +21,22 @@ const getPages = require('./pages') const getRedirects = async () => { const redirects = [] const pages = await getPages() + const { basePath } = await getNextConfig() await asyncForEach(pages, async ({ route, filePath }) => { const target = filePath.replace(/pages/, '') await addDefaultLocaleRedirect(redirects, route, target) + // For sites that use basePath, manually add necessary redirects here specific + // only to this page type (which excludes static route redirects by default) + if (basePath !== '') { + redirects.push({ + route: `${basePath}${route}`, + target: route, + }) + } + // Only create normal redirects for pages with dynamic routing if (!isDynamicRoute(route)) return diff --git a/src/lib/steps/setupRedirects.js b/src/lib/steps/setupRedirects.js index a161ad604d..50ff238d09 100644 --- a/src/lib/steps/setupRedirects.js +++ b/src/lib/steps/setupRedirects.js @@ -4,8 +4,8 @@ const { existsSync, readFileSync, writeFileSync } = require('fs-extra') const getNextConfig = require('../../../helpers/getNextConfig') const { CUSTOM_REDIRECTS_PATH, NEXT_IMAGE_FUNCTION_NAME } = require('../config') -const { DYNAMIC_PARAMETER_REGEX } = require('../constants/regex') const convertToBasePathRedirects = require('../helpers/convertToBasePathRedirects') +const formatRedirectTarget = require('../helpers/formatRedirectTarget') const getNetlifyRoutes = require('../helpers/getNetlifyRoutes') const getSortedRedirects = require('../helpers/getSortedRedirects') const isDynamicRoute = require('../helpers/isDynamicRoute') @@ -48,8 +48,7 @@ const setupRedirects = async (publishPath) => { redirects.push('# Next-on-Netlify Redirects') const { basePath } = await getNextConfig() - const hasBasePath = basePath !== '' - if (hasBasePath) { + if (basePath !== '') { nextRedirects = convertToBasePathRedirects({ basePath, nextRedirects }) } @@ -71,22 +70,18 @@ const setupRedirects = async (publishPath) => { const sortedStaticRedirects = getSortedRedirects(staticRedirects) const sortedDynamicRedirects = getSortedRedirects(dynamicRedirects) - const basePathSortFunc = (a, b) => (a.target.includes(basePath) ? -1 : 1) - const allRedirects = hasBasePath - ? [...sortedStaticRedirects.sort(basePathSortFunc), ...sortedDynamicRedirects.sort(basePathSortFunc)] - : [...sortedStaticRedirects, ...sortedDynamicRedirects] - // Assemble redirects for each route - allRedirects.forEach((nextRedirect) => { + ;[...sortedStaticRedirects, ...sortedDynamicRedirects].forEach((nextRedirect) => { // One route may map to multiple Netlify routes: e.g., catch-all pages // require two Netlify routes in the _redirects file getNetlifyRoutes(nextRedirect.route).forEach((netlifyRoute) => { const { conditions = [], force = false, statusCode = '200', target } = nextRedirect - const formattedTarget = - hasBasePath && target.includes(basePath) - ? target.replace(DYNAMIC_PARAMETER_REGEX, '/:$1').replace('...', '') - : target - const redirectPieces = [netlifyRoute, formattedTarget, `${statusCode}${force ? '!' : ''}`, conditions.join(' ')] + const redirectPieces = [ + netlifyRoute, + formatRedirectTarget({ basePath, target }), + `${statusCode}${force ? '!' : ''}`, + conditions.join(' '), + ] const redirect = redirectPieces.join(' ').trim() logItem(redirect) redirects.push(redirect) diff --git a/src/tests/__snapshots__/basePath.test.js.snap b/src/tests/__snapshots__/basePath.test.js.snap index 7df11b943e..ee4b58d4a6 100644 --- a/src/tests/__snapshots__/basePath.test.js.snap +++ b/src/tests/__snapshots__/basePath.test.js.snap @@ -2,12 +2,6 @@ exports[`Routing creates Netlify redirects 1`] = ` "# Next-on-Netlify Redirects -/getStaticProps/withRevalidate/2 /foo/getStaticProps/withRevalidate/2 301! -/getStaticProps/withRevalidate/1 /foo/getStaticProps/withRevalidate/1 301! -/getStaticProps/with-revalidate /foo/getStaticProps/with-revalidate 301! -/getServerSideProps/static /foo/getServerSideProps/static 301! -/api/static /foo/api/static 301! -/api/hello-background /foo/api/hello-background 301! / /foo 301! /_next/data/%BUILD_ID%/getServerSideProps/static.json /.netlify/functions/next_getServerSideProps_static 200 /_next/data/%BUILD_ID%/getStaticProps/1.json /.netlify/functions/next_getStaticProps_id 200! Cookie=__prerender_bypass,__next_preview_data @@ -22,34 +16,40 @@ exports[`Routing creates Netlify redirects 1`] = ` /_next/data/%BUILD_ID%/getStaticProps/withFallbackBlocking/4.json /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200! Cookie=__prerender_bypass,__next_preview_data /_next/data/%BUILD_ID%/getStaticProps/withRevalidate/1.json /.netlify/functions/next_getStaticProps_withRevalidate_id 200 /_next/data/%BUILD_ID%/getStaticProps/withRevalidate/2.json /.netlify/functions/next_getStaticProps_withRevalidate_id 200 +/api/hello-background /foo/api/hello-background 301! +/api/static /foo/api/static 301! /foo /.netlify/functions/next_index 200 +/foo/404 /404 200 /foo/_next/* /_next/:splat 301! /foo/api/hello-background /.netlify/functions/next_api_hello-background 200 /foo/api/static /.netlify/functions/next_api_static 200 /foo/getServerSideProps/static /.netlify/functions/next_getServerSideProps_static 200 -/foo/getStaticProps/1 /.netlify/functions/next_getStaticProps_id 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/2 /.netlify/functions/next_getStaticProps_id 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/static /.netlify/functions/next_getStaticProps_static 200 Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/1 /.netlify/functions/next_getStaticProps_id 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/1 /getStaticProps/1 200 +/foo/getStaticProps/2 /.netlify/functions/next_getStaticProps_id 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/2 /getStaticProps/2 200 +/foo/getStaticProps/static /.netlify/functions/next_getStaticProps_static 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/static /getStaticProps/static 200 /foo/getStaticProps/with-revalidate /.netlify/functions/next_getStaticProps_withrevalidate 200 -/foo/getStaticProps/withFallback/3 /.netlify/functions/next_getStaticProps_withFallback_id 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/withFallback/4 /.netlify/functions/next_getStaticProps_withFallback_id 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/withFallback/my/path/1 /.netlify/functions/next_getStaticProps_withFallback_slug 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/withFallback/my/path/2 /.netlify/functions/next_getStaticProps_withFallback_slug 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/withFallbackBlocking/3 /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200 Cookie=__prerender_bypass,__next_preview_data -/foo/getStaticProps/withFallbackBlocking/4 /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200 Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallback/3 /.netlify/functions/next_getStaticProps_withFallback_id 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallback/3 /getStaticProps/withFallback/3 200 +/foo/getStaticProps/withFallback/4 /.netlify/functions/next_getStaticProps_withFallback_id 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallback/4 /getStaticProps/withFallback/4 200 +/foo/getStaticProps/withFallback/my/path/1 /.netlify/functions/next_getStaticProps_withFallback_slug 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallback/my/path/1 /getStaticProps/withFallback/my/path/1 200 +/foo/getStaticProps/withFallback/my/path/2 /.netlify/functions/next_getStaticProps_withFallback_slug 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallback/my/path/2 /getStaticProps/withFallback/my/path/2 200 +/foo/getStaticProps/withFallbackBlocking/3 /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallbackBlocking/3 /getStaticProps/withFallbackBlocking/3 200 +/foo/getStaticProps/withFallbackBlocking/4 /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200! Cookie=__prerender_bypass,__next_preview_data +/foo/getStaticProps/withFallbackBlocking/4 /getStaticProps/withFallbackBlocking/4 200 /foo/getStaticProps/withRevalidate/1 /.netlify/functions/next_getStaticProps_withRevalidate_id 200 /foo/getStaticProps/withRevalidate/2 /.netlify/functions/next_getStaticProps_withRevalidate_id 200 -/shows/:params/* /foo/shows/:params 301! -/shows/:id /foo/shows/:id 301! -/getStaticProps/withRevalidate/withFallback/:id /foo/getStaticProps/withRevalidate/withFallback/:id 301! -/getStaticProps/withFallbackBlocking/:id /foo/getStaticProps/withFallbackBlocking/:id 301! -/getStaticProps/withFallback/:slug/* /foo/getStaticProps/withFallback/:slug 301! -/getStaticProps/withFallback/:id /foo/getStaticProps/withFallback/:id 301! -/getServerSideProps/:id /foo/getServerSideProps/:id 301! -/getServerSideProps/all /foo/getServerSideProps/all/:[slug] 301! -/getServerSideProps/all/* /foo/getServerSideProps/all/:[slug] 301! -/api/shows/:params/* /foo/api/shows/:params 301! -/api/shows/:id /foo/api/shows/:id 301! +/foo/static /static 200 +/getServerSideProps/static /foo/getServerSideProps/static 301! +/getStaticProps/with-revalidate /foo/getStaticProps/with-revalidate 301! +/getStaticProps/withRevalidate/1 /foo/getStaticProps/withRevalidate/1 301! +/getStaticProps/withRevalidate/2 /foo/getStaticProps/withRevalidate/2 301! /_next/data/%BUILD_ID%/getServerSideProps/all.json /.netlify/functions/next_getServerSideProps_all_slug 200 /_next/data/%BUILD_ID%/getServerSideProps/all/* /.netlify/functions/next_getServerSideProps_all_slug 200 /_next/data/%BUILD_ID%/getServerSideProps/:id.json /.netlify/functions/next_getServerSideProps_id 200 @@ -57,6 +57,8 @@ exports[`Routing creates Netlify redirects 1`] = ` /_next/data/%BUILD_ID%/getStaticProps/withFallback/:slug/* /.netlify/functions/next_getStaticProps_withFallback_slug 200 /_next/data/%BUILD_ID%/getStaticProps/withFallbackBlocking/:id.json /.netlify/functions/next_getStaticProps_withFallbackBlocking_id 200 /_next/data/%BUILD_ID%/getStaticProps/withRevalidate/withFallback/:id.json /.netlify/functions/next_getStaticProps_withRevalidate_withFallback_id 200 +/api/shows/:id /foo/api/shows/:id 301! +/api/shows/:params/* /foo/api/shows/:params 301! /foo/_next/image* url=:url w=:width q=:quality /nextimg/:url/:width/:quality 301! /foo/api/shows/:id /.netlify/functions/next_api_shows_id 200 /foo/api/shows/:params/* /.netlify/functions/next_api_shows_params 200 @@ -69,6 +71,16 @@ exports[`Routing creates Netlify redirects 1`] = ` /foo/getStaticProps/withRevalidate/withFallback/:id /.netlify/functions/next_getStaticProps_withRevalidate_withFallback_id 200 /foo/shows/:id /.netlify/functions/next_shows_id 200 /foo/shows/:params/* /.netlify/functions/next_shows_params 200 +/foo/static/:id /static/[id] 200 +/getServerSideProps/all /foo/getServerSideProps/all/:slug 301! +/getServerSideProps/all/* /foo/getServerSideProps/all/:slug 301! +/getServerSideProps/:id /foo/getServerSideProps/:id 301! +/getStaticProps/withFallback/:id /foo/getStaticProps/withFallback/:id 301! +/getStaticProps/withFallback/:slug/* /foo/getStaticProps/withFallback/:slug 301! +/getStaticProps/withFallbackBlocking/:id /foo/getStaticProps/withFallbackBlocking/:id 301! +/getStaticProps/withRevalidate/withFallback/:id /foo/getStaticProps/withRevalidate/withFallback/:id 301! /nextimg/* /.netlify/functions/next_image 200 +/shows/:id /foo/shows/:id 301! +/shows/:params/* /foo/shows/:params 301! /static/:id /static/[id].html 200" `;