Next.js Discord

Discord Forum

Middleware redirection is rendering the correct page but not changing browser url

Unanswered
GuitarNerd posted this in #help-forum
Open in Discord
Avatar
Hi everyone,

This issue seems to resurface with me I don't know why, possibly due to updating Next.js.
Below you will find my middleware.

In one of those cases I have 2 redirects:
- User logs in. Code sends it to the dashboard.
- Middleware realises user was not approved by the admin: redirect to a page informing user their account is awaiting approval.

And here are the relevant parts in my server actions:

"use server"

import { revalidatePath, revalidateTag } from "next/cache"
import { cookies } from "next/headers"

import { IUser, IUserAuth } from "@/types/global"
import { USER } from "@/api"

import { extractResponseData, userCookieData } from "./helpers"

export const setUser = (user: IUser | null, token: string) => {
  if (user) {
    cookies().set(
      "user",
      JSON.stringify({
        token,
        user: userCookieData(user),
      })
    )
  } else {
    cookies().delete("user")
  }
}

export const getUser = async () => {
  "use server"

  const user = cookies().get("user")
  if (!user) {
    try {
      const response = await fetch(USER.url, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${cookies().get("token")}`,
        },
      })
      if (response.ok) {
        const { data } = await extractResponseData(response)
        setUser((data as IUserAuth).user as IUser, (data as IUserAuth).access_token)
      }
    } catch (err) {
      console.log(err)
    }
  }
  return cookies().get("user")
}
Image

21 Replies

Avatar
bump
Avatar
I don't see any issue there. could you try return NextResponse.redirect(new URL("/path", req.url)) and see it the url change?
Avatar
Thank you for your answer and taking the time!

I did that. I added 307 after reading the documentation just as a potential last resort, it didn't help.

I'm wondering if the rewrites in next.config.js could be affecting that ?

    async rewrites() {
        return [
            {
                source: '/signup/:path*',
                destination: '/auth/signup/:path*',
            },
            {
                source: '/login',
                destination: '/auth/login',
            },
            {
                source: '/created',
                destination: '/auth/created',
            },
            {
                source: '/forgot-password/:path*',
                destination: '/auth/forgot-password/:path*',
            },
            {
                source: '/waiting',
                destination: '/auth/waiting',
            },
            {
                source: '/verification/:path*',
                destination: '/auth/verification/:path*',
            },
        ]
    },
Avatar
oh yeah it will affect
rewrite won't change the url
Avatar
Currently when I'm redirecting I'm using the URL in source. Should I use the one in destination ?

That would be a little odd because it's working on some URLs and not on others
I'll give it a shot when I'm back from the dentist. Thanks!
Avatar
yes use the one in destination should do it
Avatar
Didn't work. For a temporary workaround i'm doing a setTimeout on the frontend where i'm using router.push but i'll look into it again in another sprint
Avatar
for example, /auth/login is the real path of /login right?
Avatar
Yes
I'm thinking that perhaps the router.push is happening before the server action has completed setting my cookies and that is causing my frontend router and my server router to have a delay. Which is why the frontend is rendering correctly but the browser url isn't changing.
This is further supported by the fact that:

- When I refresh the browser url is updated correctly(so it seems there is a delay)
- setTimeout is fixing it.
Avatar
oh where do you use router.push? do you use router.push on all the page and does all the page not changine the url?
Avatar
I am using router.push in my AuthContext which calls a server action. I didn't originally include them as I thought the issue is isolated to the middleware. Adding them below
Image
the settimeout is a workaround that lets me bypass the issue but obviously i'd like to get rid of it
"use server"

import { revalidatePath, revalidateTag } from "next/cache"
import { cookies } from "next/headers"

import { IUser, IUserAuth } from "@/types/global"
import { USER } from "@/api"

import { extractResponseData, userCookieData } from "./helpers"

export const setUser = (user: IUser | null, token: string) => {
  if (user) {
    cookies().set(
      "user",
      JSON.stringify({
        token,
        user: userCookieData(user),
      })
    )
  } else {
    cookies().delete("user")
  }
}

export const getUser = async () => {
  "use server"

  const user = cookies().get("user")
  if (!user) {
    try {
      const response = await fetch(USER.url, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${cookies().get("token")}`,
        },
      })
      if (response.ok) {
        const { data } = await extractResponseData(response)
        setUser((data as IUserAuth).user as IUser, (data as IUserAuth).access_token)
      }
    } catch (err) {
      console.log(err)
    }
  }
  return cookies().get("user")
}

Server Actions
Avatar
could you do a test on a page without context and router.push and see if the url change correctly?
Avatar
@Ray yes it does
Avatar
ok so should be something wrong on client side. what is the url you use on router.push? the source one or the destination one on the rewrites?