Repository: vercel/next.js
Pull request: fix: Proxy not picked up on Windows

Proxy is not being picked up during prod on Windows. It is because of two reasons:

1. `isAtConventionLevel` condition was false as the dir was `\\` in Windows, but was checking with explicit `/`.
2. `page` value passed to `getStaticInfoIncludingLayouts` function was in `\\proxy` but was expected to be `/proxy`, which is later used for `isProxy` condition.

Therefore, the given paths needed to be normalized.

Current behavior: https://github.com/vercel/next.js/actions/runs/18872127141/job/53853048061?pr=85443#step:34:160

Closes NEXT-4756

Changed files:
filename: .github/workflows/build_and_test.yml
patch: @@ -764,6 +764,7 @@ jobs:
         node run-tests.js \
           test/e2e/app-dir/app/index.test.ts \
           test/e2e/app-dir/app-edge/app-edge.test.ts \
+          test/e2e/app-dir/proxy-runtime-nodejs/proxy-runtime-nodejs.test.ts \
           test/development/app-dir/segment-explorer/segment-explorer.test.ts
       stepName: 'test-dev-windows'
       runs_on_labels: '["windows","self-hosted","x64"]'
@@ -821,7 +822,8 @@ jobs:
           test/e2e/app-dir/app/index.test.ts \
           test/e2e/app-dir/app-edge/app-edge.test.ts \
           test/e2e/app-dir/metadata-edge/index.test.ts \
-          test/e2e/app-dir/non-root-project-monorepo/non-root-project-monorepo.test.ts
+          test/e2e/app-dir/non-root-project-monorepo/non-root-project-monorepo.test.ts \
+          test/e2e/app-dir/proxy-runtime-nodejs/proxy-runtime-nodejs.test.ts
       stepName: 'test-prod-windows'
       runs_on_labels: '["windows","self-hosted","x64"]'
       buildNativeTarget: 'x86_64-pc-windows-msvc'

filename: packages/next/src/build/index.ts
patch: @@ -1215,7 +1215,10 @@ export default async function build(
 
       for (const rootPath of rootPaths) {
         const { name: fileBaseName, dir: fileDir } = path.parse(rootPath)
-        const isAtConventionLevel = fileDir === '/' || fileDir === '/src'
+
+        const normalizedFileDir = normalizePathSep(fileDir)
+        const isAtConventionLevel =
+          normalizedFileDir === '/' || normalizedFileDir === '/src'
 
         if (isAtConventionLevel && fileBaseName === MIDDLEWARE_FILENAME) {
           middlewareFilePath = rootPath
@@ -2610,7 +2613,9 @@ export default async function build(
           return serverFilesManifest
         })
 
-      const middlewareFile = proxyFilePath || middlewareFilePath
+      const middlewareFile = normalizePathSep(
+        proxyFilePath || middlewareFilePath || ''
+      )
       let hasNodeMiddleware = false
 
       if (middlewareFile) {

filename: packages/next/src/server/next-server.ts
patch: @@ -1574,10 +1574,6 @@ export default class NextNodeServer extends BaseServer<
           functionsConfig?.functions?.['/_middleware']
         ) {
           // if used with top level await, this will be a promise
-          // Try loading middleware.js first, then proxy.js. Instead
-          // of mapping proxy to middleware as the entry, just fallback
-          // to proxy.
-          // TODO: Remove this once we handle as the single entrypoint.
           return require(
             join(
               /* turbopackIgnore: true */ this.distDir,