vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.12k stars 26.73k forks source link

Middleware not being triggered #68581

Open utkarshk384 opened 1 month ago

utkarshk384 commented 1 month ago

Link to the code that reproduces this issue

https://github.com/utkarshk384/nextjs-repro

To Reproduce

  1. Run npm install
  2. Start the server with npm run dev

Current vs. Expected behavior

Middlewares are triggered randomly with no clear trigger pattern. To replicate the issue you can perform the following actions:

  1. Head to / route
  2. Click on Authenicated Route to get redirected with a search param of login=0
  3. Now click on Set Cookie and then Click on Authenticated Route again
  4. This time the middleware won't be triggered as the message won't be console logged.
  5. Now if you hard refresh and click on Authenticated Route then you'll be able to access the authenticated route. However when I click go back to the root route, and click on Delete Cookie and try accessing the route then for some reason I am still able to access the route even without the cookie.

Expected Behaviour

When logged in, the authenticated route should be accessible without any issues and when not then the user should be redirected to / route with login=0 search param.

Current Behavior

User is randomly being redirected to authenticated route and sometimes even with the cookie the middleware is not being triggered.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000
  Available memory (MB): 16384
  Available CPU cores: 8
Binaries:
  Node: 20.11.0
  npm: 10.2.4
  Yarn: 1.22.19
  pnpm: N/A
Relevant Packages:
  next: 14.2.5 // Latest available version is detected (14.2.5).
  eslint-config-next: 14.2.5
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.5.4
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Middleware, Navigation, Runtime

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), next start (local)

Additional context

I've tested with the next 14.2.5 and with next js version ^13.5.6 and in both cases the issue is persistant.

samcx commented 1 month ago

@utkarshk384 I am unable to replicate these issues on the latest canary. Can you try again on the latest canary?

utkarshk384 commented 1 month ago

@samcx , I tired with next@15.0.0-canary.106 and it seems it I am unable to access the authenticated route if the cookie is not present which is the expected behavior. However, the middleware is not being triggered when the cookie is already being set. I've done a short recording for the exact procedure. Do let me know if you could reproduce the issue as per the steps below.

https://github.com/user-attachments/assets/6cbc9bf4-28ce-4210-9816-1e6620cee858

PS: Only after a page refresh I'm able to load the authenticated page with the cookie.

samcx commented 1 month ago

@utkarshk384 From the video, it's not clear that the Middleware is ran or not (you have to show the console in the terminal). For example, when you delete the cookie, it's not reflected immediately. I don't believe you are using a Server Action (or you can use a Route Handler instead) to handle cookie actions, so it's not being reflected immediately.

Can you try adding the use server directive to your cookie utils?

utkarshk384 commented 1 month ago

@samcx I completely forgot about the terminal aspect, therefore, there's another recording with the terminal below. As for the cookie changes, I'm currently doing it from the client but in the real application the cookies are completely managed by the server.

Also as a side note the matchers for middleware is set to {matcher: ["/login"]}

https://github.com/user-attachments/assets/89ab6fa0-8af1-4814-8cdb-c3b8542d476b

samcx commented 1 month ago

@utkarshk384 I don't think the Middleware is not triggering, but I do think there might be some issue with HMR? or something that doesn't cause it to show the log at first.

68581-middleware-not-triggered [main] p dev

> .../68581-middleware-not-triggered
> next dev --turbo

  ▲ Next.js 15.0.0-canary.106 (turbo)
  - Local:        http://localhost:3000

 ✓ Starting...
 ✓ Compiled in 95ms
 ✓ Ready in 611ms
 ○ Compiling / ...
 ✓ Compiled / in 896ms
 GET / 200 in 976ms
 GET /?login=0 200 in 56ms // I should have seen a Middleware log before this
URL /login { name: 'login', value: '1' } // clicked on set cookie then went to clicked to go to /login again
basePath = http://localhost:3000
 ✓ Compiled /login in 47ms
 GET /login 200 in 63ms

Can you try adding the use server directive to your cookie utils?

utkarshk384 commented 1 month ago

@samcx I tried with use server directive as well but it didn't work :(. I also tried to check if it could be an issue with the HMR module by building a production environment and running it there. However, even on production the issue persists.

I suspect that if the middleware response is being cached, then there's always a cache hit therefore, completely ignoring the middleware. This is just my assumption and could be completely wrong as I've got no clue about the next codebase. Maybe I'll try to see if I can go through the codebase this weekend and see if I can understand.

I've attached a recording for the tests I've made and have also updated the repo for your side of testing with the server action cookies.

https://github.com/user-attachments/assets/61713097-6082-4c93-a0a6-509254729fab

utkarshk384 commented 1 month ago

Hello @samcx, is there any update on the issue ? Im trying to look for alternative ways for authenticating as well but would be very elated if the middleware worked.

samcx commented 1 month ago

@utkarshk384 Still investigating!

When I start up the server fresh, the way it's replicable for me is if I click on Authenticated Route twice. If I press it once (with no cookie set), set the cookie, then click Authenticated Route again, it works fine. Can you also try testing this?

Have you also tried deploying your :repro: to see if it's replicable similarly?

utkarshk384 commented 1 month ago

Okay, so I tried the steps that you mentioned and it is working as expected.

However, when we start a fresh server and click on Set-Cookie once and then authenticated route then the middleware seems to fail. Therefore, could you check the same at your end as well? I think this replicates a real world scenario as well; we first set cookie after user logs in then route them to the route using useRouter.

I've also deployed the repro on Vercel and everything seems to be working as expected. Here's the link. However, I'm puzzled on why its failing in development and local production🥲.

Also thanks for following up closely with the issue :)