diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts
index a15debacc40b1..0a22081d29d70 100644
--- a/packages/next/next-server/server/next-server.ts
+++ b/packages/next/next-server/server/next-server.ts
@@ -431,7 +431,6 @@ export default class Server {
.replace(/\.json$/, '')
.replace(/\/index$/, '/')
- req.url = pathname
const parsedUrl = parseUrl(pathname, true)
await this.render(
req,
@@ -794,9 +793,14 @@ export default class Server {
const url: any = req.url
+ // we allow custom servers to call render for all URLs
+ // so check if we need to serve a static _next file or not.
+ // we don't modify the URL for _next/data request but still
+ // call render so we special case this to prevent an infinite loop
if (
- url.match(/^\/_next\//) ||
- (this.hasStaticDir && url.match(/^\/static\//))
+ !query._nextDataReq &&
+ (url.match(/^\/_next\//) ||
+ (this.hasStaticDir && url.match(/^\/static\//)))
) {
return this.handleRequest(req, res, parsedUrl)
}
@@ -926,17 +930,6 @@ export default class Server {
const isDataReq = !!query._nextDataReq
delete query._nextDataReq
- // Serverless requests need its URL transformed back into the original
- // request path (to emulate lambda behavior in production)
- if (isLikeServerless && isDataReq) {
- let { pathname } = parseUrl(req.url || '', true)
- pathname = !pathname || pathname === '/' ? '/index' : pathname
- req.url = formatUrl({
- pathname: `/_next/data/${this.buildId}${pathname}.json`,
- query,
- })
- }
-
let previewData: string | false | object | undefined
let isPreviewMode = false
@@ -1009,10 +1002,19 @@ export default class Server {
return html
}
- // Compute the SPR cache key
- const urlPathname = `${parseUrl(req.url || '').pathname!}${
+ // Compute the iSSG cache key
+ let urlPathname = `${parseUrl(req.url || '').pathname!}${
query.amp ? '.amp' : ''
}`
+
+ // remove /_next/data prefix from urlPathname so it matches
+ // for direct page visit and /_next/data visit
+ if (isDataReq && urlPathname.includes(this.buildId)) {
+ urlPathname = (urlPathname.split(this.buildId).pop() || '/')
+ .replace(/\.json$/, '')
+ .replace(/\/index$/, '/')
+ }
+
const ssgCacheKey = isPreviewMode
? `__` + nanoid() // Preview mode uses a throw away key to not coalesce preview invokes
: urlPathname
diff --git a/test/integration/getserversideprops/pages/_app.js b/test/integration/getserversideprops/pages/_app.js
new file mode 100644
index 0000000000000..07a84bbe06577
--- /dev/null
+++ b/test/integration/getserversideprops/pages/_app.js
@@ -0,0 +1,29 @@
+import App from 'next/app'
+
+class MyApp extends App {
+ static async getInitialProps(ctx) {
+ const { req, query, pathname, asPath } = ctx.ctx
+ let pageProps = {}
+
+ if (ctx.Component.getInitialProps) {
+ pageProps = await ctx.Component.getInitialProps(ctx.ctx)
+ }
+
+ return {
+ appProps: {
+ url: (req || {}).url,
+ query,
+ pathname,
+ asPath,
+ },
+ pageProps,
+ }
+ }
+
+ render() {
+ const { Component, pageProps, appProps } = this.props
+ return
Post: {post}
time: {time}hello: {world}
@@ -23,6 +23,8 @@ export default ({ world, time, params, random, query }) => {