[Bug]: Middleware rewrites cause infinite redirect loop when pointing to a directory in `public`
cprussin opened this issue · 2 comments
Summary
Given the following middleware:
export default (request) => NextResponse.rewrite(new URL('/foo', request.url));
If there's a folder /foo
in /public
, requests enter an infinite redirect loop.
Note this is almost certainly related to #2331 , and I'd bet it's cause by the same underlying root issue. The difference between this ticket and that one is that here we use NextResponse.rewrite
instead of MiddlewareRequest.rewrite
, and instead of an error we get an infinite redirect loop.
A link to a reproduction repository
https://github.com/cprussin/netlify-issue-repro-2
Expected Result
Render the file /public/foo/index.html
if it exists, and 404 if it does not.
Actual Result
Infinite redirect loop
Steps to reproduce
- Deploy repo
- Navigate to site
Next Runtime version
4.40.2
Is your issue related to the app
directory?
- Yes, I am using the
app
directory
More information about your build
- I am building using the CLI
- I am building using file-based configuration (
netlify.toml
)
What OS are you using?
None
Your netlify.toml file
No response
Your public/_redirects file
No response
Your next.config.js
file
`next.config.js`
module.exports = {
reactStrictMode: true
};
Builds logs (or link to your logs)
Build logs
6:27:29 AM: build-image version: 2a79f2b6b97edab3f858983ec4cea00280a2836a (focal)
6:27:29 AM: buildbot version: c7db8131ac2d97256c1f537cc5bbdf08464b8daa
6:27:29 AM: Fetching cached dependencies
6:27:29 AM: Starting to download cache of 201.6MB
6:27:30 AM: Finished downloading cache in 544ms
6:27:30 AM: Starting to extract cache
6:27:32 AM: Finished extracting cache in 2.525s
6:27:32 AM: Finished fetching cache in 3.127s
6:27:32 AM: Starting to prepare the repo for build
6:27:32 AM: Preparing Git Reference refs/heads/master
6:27:34 AM: Starting to install dependencies
6:27:34 AM: Python version set to 3.8
6:27:34 AM: Attempting Ruby version 2.7.2, read from environment
6:27:35 AM: Using Ruby version 2.7.2
6:27:35 AM: Started restoring cached go cache
6:27:35 AM: Finished restoring cached go cache
6:27:35 AM: go version go1.19.13 linux/amd64
6:27:36 AM: Using PHP version 8.0
6:27:37 AM: Started restoring cached Node.js version
6:27:38 AM: Finished restoring cached Node.js version
6:27:39 AM: v18.18.2 is already installed.
6:27:39 AM: Now using node v18.18.2 (npm v9.8.1)
6:27:39 AM: Enabling Node.js Corepack
6:27:39 AM: Started restoring cached build plugins
6:27:39 AM: Finished restoring cached build plugins
6:27:39 AM: Started restoring cached corepack dependencies
6:27:39 AM: Finished restoring cached corepack dependencies
6:27:39 AM: No pnpm workspaces detected
6:27:39 AM: Started restoring cached node modules
6:27:39 AM: Finished restoring cached node modules
6:27:40 AM: Installing npm packages using pnpm version 8.7.6
6:27:40 AM: Lockfile is up to date, resolution step is skipped
6:27:40 AM: Already up to date
6:27:40 AM: Done in 467ms
6:27:40 AM: npm packages installed using pnpm
6:27:41 AM: Install dependencies script success
6:27:41 AM: Starting build script
6:27:42 AM: Detected 1 framework(s)
6:27:42 AM: "next" at version "13.5.4"
6:27:42 AM: Section completed: initializing
6:27:44 AM:
6:27:44 AM: Netlify Build
6:27:44 AM: ────────────────────────────────────────────────────────────────
6:27:44 AM:
6:27:44 AM: ❯ Version
6:27:44 AM: @netlify/build 29.22.5
6:27:44 AM:
6:27:44 AM: ❯ Flags
6:27:44 AM: baseRelDir: true
6:27:44 AM: buildId: 652a973f3a0d00000817e314
6:27:44 AM: deployId: 652a973f3a0d00000817e316
6:27:44 AM:
6:27:44 AM: ❯ Current directory
6:27:44 AM: /opt/build/repo
6:27:44 AM:
6:27:44 AM: ❯ Config file
6:27:44 AM: No config file was defined: using default values.
6:27:44 AM:
6:27:44 AM: ❯ Context
6:27:44 AM: production
6:27:44 AM:
6:27:44 AM: ❯ Using Next.js Runtime - v4.40.2
6:27:45 AM:
6:27:45 AM: @netlify/plugin-nextjs (onPreBuild event)
6:27:45 AM: ────────────────────────────────────────────────────────────────
6:27:45 AM:
6:27:45 AM: Next.js cache restored.
6:27:45 AM: Netlify configuration property "build.environment.NEXT_PRIVATE_TARGET" value changed.
6:27:45 AM:
6:27:45 AM: (@netlify/plugin-nextjs onPreBuild completed in 111ms)
6:27:45 AM:
6:27:45 AM: Build command from Netlify app
6:27:45 AM: ────────────────────────────────────────────────────────────────
6:27:45 AM:
6:27:45 AM: $ pnpm run build
6:27:45 AM: > next-test@1.0.0 build /opt/build/repo
6:27:45 AM: > next build
6:27:46 AM: Creating an optimized production build ...
6:27:48 AM: ✓ Compiled successfully
6:27:48 AM: Linting and checking validity of types ...
6:27:48 AM: Collecting page data ...
6:27:50 AM: Generating static pages (0/4) ...
6:27:51 AM: Generating static pages (1/4)
6:27:51 AM: Generating static pages (2/4)
6:27:51 AM: Generating static pages (3/4)
6:27:51 AM: ✓ Generating static pages (4/4)
6:27:53 AM: Finalizing page optimization ...
6:27:53 AM: Collecting build traces ...
6:27:54 AM: Route (app) Size First Load JS
6:27:54 AM: ┌ ○ / 140 B 80.5 kB
6:27:54 AM: └ ○ /_not-found 883 B 81.2 kB
6:27:54 AM: + First Load JS shared by all 80.3 kB
6:27:54 AM: ├ chunks/95-667055ea6e31680b.js 27.5 kB
6:27:54 AM: ├ chunks/b97a3a71-357a375a396d8622.js 51 kB
6:27:54 AM: ├ chunks/main-app-968e29e1596532ac.js 229 B
6:27:54 AM: └ chunks/webpack-bf1a64d1eafd2816.js 1.66 kB
6:27:54 AM: ƒ Middleware 25 kB
6:27:54 AM: ○ (Static) automatically rendered as static HTML (uses no initial props)
6:27:55 AM:
6:27:55 AM: (build.command completed in 9.5s)
6:27:55 AM:
6:27:55 AM: @netlify/plugin-nextjs (onBuild event)
6:27:55 AM: ────────────────────────────────────────────────────────────────
6:27:55 AM:
6:27:55 AM: Moving static page files to serve from CDN...
6:27:55 AM: Moved 6 files
6:27:55 AM: You are not using Netlify Edge Functions for image format detection. Set env var "NEXT_FORCE_EDGE_IMAGES=true" to enable.
6:27:55 AM: ✨ Deploying middleware and functions to Netlify Edge Functions ✨
6:27:55 AM: Netlify configuration property "redirects" value changed to [
6:27:55 AM: { from: "/_next/static/*", to: "/static/:splat", status: 200 },
6:27:55 AM: {
6:27:55 AM: from: "/_next/image*",
6:27:55 AM: query: { url: ":url", w: ":width", q: ":quality" },
6:27:55 AM: to: "/_ipx/w_:width,q_:quality/:url",
6:27:55 AM: status: 301
6:27:55 AM: },
6:27:55 AM: { from: "/_ipx/*", to: "/.netlify/builders/_ipx", status: 200 },
6:27:55 AM: {
6:27:55 AM: from: "/api/*",
6:27:55 AM: to: "/.netlify/functions/___netlify-handler",
6:27:55 AM: status: 200
6:27:55 AM: },
6:27:55 AM: {
6:27:55 AM: from: "/foo/index.html",
6:27:55 AM: to: "/foo/index.html",
6:27:55 AM: conditions: { Cookie: [Array] },
6:27:55 AM: status: 200
6:27:55 AM: },
6:27:55 AM: {
6:27:55 AM: from: "/*",
6:27:55 AM: to: "/.netlify/functions/___netlify-handler",
6:27:55 AM: status: 200,
6:27:55 AM: conditions: { Cookie: [Array] },
6:27:55 AM: force: true
6:27:55 AM: },
6:27:55 AM: {
6:27:55 AM: from: "/_next/data/HIbEp6Vx_qa969jm4QjQU/_not-found.json",
6:27:55 AM: to: "/.netlify/functions/___netlify-handler",
6:27:55 AM: status: 200,
6:27:55 AM: force: false
6:27:55 AM: },
6:27:55 AM: {
6:27:55 AM: from: "/_not-found",
6:27:55 AM: to: "/.netlify/functions/___netlify-handler",
6:27:55 AM: status: 200,
6:27:55 AM: force: false
6:27:55 AM: },
6:27:55 AM: {
6:27:55 AM: from: "/*",
6:27:55 AM: to: "/.netlify/functions/___netlify-handler",
6:27:55 AM: status: 200
6:27:55 AM: }
6:27:55 AM: ].
6:27:55 AM:
6:27:55 AM: (@netlify/plugin-nextjs onBuild completed in 190ms)
6:27:55 AM:
6:27:55 AM: Functions bundling
6:27:55 AM: ────────────────────────────────────────────────────────────────
6:27:55 AM:
6:27:55 AM: Packaging Functions from .netlify/functions-internal directory:
6:27:55 AM: - ___netlify-handler/___netlify-handler.js
6:27:55 AM: - ___netlify-odb-handler/___netlify-odb-handler.js
6:27:55 AM: - _ipx/_ipx.js
6:27:55 AM:
6:28:30 AM:
6:28:30 AM: (Functions bundling completed in 35.4s)
6:28:30 AM:
6:28:30 AM: Edge Functions bundling
6:28:30 AM: ────────────────────────────────────────────────────────────────
6:28:30 AM:
6:28:30 AM: Packaging Edge Functions from .netlify/edge-functions directory:
6:28:30 AM: - next_src_middleware
6:28:30 AM: - rsc-data
6:28:32 AM:
6:28:32 AM: (Edge Functions bundling completed in 1.6s)
6:28:32 AM:
6:28:32 AM: @netlify/plugin-nextjs (onPostBuild event)
6:28:32 AM: ────────────────────────────────────────────────────────────────
6:28:32 AM:
6:28:32 AM: Next.js cache saved.
6:28:32 AM:
6:28:32 AM: (@netlify/plugin-nextjs onPostBuild completed in 66ms)
6:28:32 AM:
6:28:32 AM: Deploy site
6:28:32 AM: ────────────────────────────────────────────────────────────────
6:28:32 AM:
6:28:32 AM: Starting to deploy site from ".next"
6:28:32 AM: Calculating files to upload
6:28:32 AM: 8 new files to upload
6:28:32 AM: 2 new functions to upload
6:28:41 AM: Skipping HTML post processing
6:28:41 AM: Post processing - header rules
6:28:41 AM: Starting post processing
6:28:41 AM: Section completed: deploying
6:28:41 AM: Site deploy was successfully initiated
6:28:41 AM:
6:28:41 AM: (Deploy site completed in 8.7s)
6:28:41 AM:
6:28:41 AM: Netlify Build Complete
6:28:41 AM: ────────────────────────────────────────────────────────────────
6:28:41 AM:
6:28:41 AM: (Netlify Build completed in 57.2s)
6:28:41 AM: Caching artifacts
6:28:41 AM: Started saving node modules
6:28:41 AM: Finished saving node modules
6:28:41 AM: Started saving build plugins
6:28:41 AM: Finished saving build plugins
6:28:41 AM: Started saving corepack cache
6:28:41 AM: Finished saving corepack cache
6:28:41 AM: Started saving pip cache
6:28:41 AM: Finished saving pip cache
6:28:41 AM: Started saving emacs cask dependencies
6:28:41 AM: Finished saving emacs cask dependencies
6:28:41 AM: Started saving maven dependencies
6:28:41 AM: Finished saving maven dependencies
6:28:41 AM: Started saving boot dependencies
6:28:41 AM: Finished saving boot dependencies
6:28:41 AM: Started saving rust rustup cache
6:28:41 AM: Finished saving rust rustup cache
6:28:41 AM: Started saving go dependencies
6:28:41 AM: Finished saving go dependencies
6:28:41 AM: Build script success
6:28:41 AM: Section completed: building
6:28:43 AM: Uploading Cache of size 201.6MB
6:28:44 AM: Section completed: cleanup
6:28:44 AM: Finished processing build request in 1m15.444s
6:28:41 AM: Post processing - redirect rules
6:28:41 AM: Post processing done
6:28:41 AM: Section completed: postprocessing
6:28:42 AM: Site is live ✨
Function logs
N/A -- logs are empty
.next JSON files
No response
This appears to be related to Pretty URLs -- disabling Pretty URLs causes the infinite redirect to go away. However, strangely, when using this middleware with pretty URLs disabled, I'm still getting behavior that matches pretty URLs, i.e. a rewrite to /foo is actually pointing to /foo/index.html.
So it appears that there's some issue with how pretty URLs interacts with next apps. I'm not sure if what I'm seeing is intended functionality or a bug, but it works for my use case -- I'll leave this ticket open in case it's considered unexpected functionality.