Open anni1236012 opened 1 year ago
@anni1236012 try setting the status code to 303. One of the reasons it might fail is because of the browser cache. By default NextResponse.redirect will do a 307, which can be cahced by the browser.
return NextResponse.redirect(new URL("/login", request.url), {
status: 303,
});
@SuhelMakkad it did not change the behavior.
Interesting 🤔 I am using this exact setup for my app and it works fine. I tried your repo on my local machine, and after the changes it worked. Maybe you need to clear your browser cache.
I have exactly the same problem, it does not give the expected behaviour for a while
I fixed it with rewrite instead of redirect.
return NextResponse.rewrite(new URL("/login", request.url), {
status: 303,
});
@anni1236012 no, the problem is not solved. a short time still does not give the expected result
@yasermazlum Please share your github link to recreate the issue.
try to avoid loading cached page append random query on querystring ex) localhost:3000/hello=${Date.now()}
I also stucked at login page, when I debug see that The user object found and returns true response. But the status code is 303
At NextJS 15 (canary version) it was fixed, the server middleware is correct changing the browser URL after NextResponse.redirect
.
But I guess I found another error when passing a hash parameter /some-url#value-here
, the hash parameter is not sending with the redirected URL.
The problem was not completely fixed.
I am experiencing an issue with the middleware. I need to route the user based on their role
, but the middleware is not able to route properly. Here's the explanation:
I have two roles in my app, manager
and staff
, and a user can have either of these roles in their respective org
.
When the user changes the org
using a dropdown in the UI, the middleware is supposed to detect the new selected org
and route the user to the corresponding URL. I've written the following logic for this:
if (orgRole === 'manager' && request.nextUrl.pathname.includes('/staff')) {
const url = request.nextUrl.clone()
url.pathname = `${orgShortId}/dashboard/manager/app`
return NextResponse.redirect(url, { status: 303 })
}
if (orgRole === 'staff' && request.nextUrl.pathname.includes('/manager')) {
const url = request.nextUrl.clone()
url.pathname = `${orgShortId}/dashboard/staff/app`
return NextResponse.redirect(url, { status: 303 })
}
However, the issue I'm facing is that the app is not getting routed to the URL as expected; it remains unchanged.
might need to use router.refresh
I'm facing a similar issue, where in this middleware :
import { NextRequest, NextResponse } from "next/server";
import unauthorizedRoutes from "./utils/routes";
import evaluateTokensStatus from "./utils/evaluateTokens";
export async function middleware(request: NextRequest) {
let tokensStatus = evaluateTokensStatus();
const isAuthenticated =
tokensStatus === "valid" || tokensStatus === "expired";
const isUnauthorizedRoute = unauthorizedRoutes.some((route) =>
request.nextUrl.pathname.startsWith(route)
);
console.log("isUnauthorizedRoute", isUnauthorizedRoute);
console.log("isAuthenticated", isAuthenticated);
if (!isAuthenticated && !isUnauthorizedRoute) {
return NextResponse.redirect(new URL("/auth/login", request.url), {
status: 303,
});
}
if (isAuthenticated && isUnauthorizedRoute) {
console.log("should redirect to /");
return NextResponse.redirect(new URL("/", request.url), {
status: 303,
});
}
return NextResponse.next();
}
export const config = {
matcher: ["/((?!api|_next/static|_next/image|.*\\.png$).*)"],
};
When redirect should happen it is not working, and nothing happens.
Strange thing ....
Any solution to this? I have the same issue. NextResponse.redirect doesn't redirect but stays on the same site. I'm using 14.3.0-canary.30, adding status 303 to redirect doesn't help either.
I did one workaround though it is not a perfect solution but it worked fine in my case.
I have one drop-down through which I am changing the orgs
in user accounts so when the user switches between orgs I add one line in the click event,
window.location.href = "/"
So here what happens is, the app sends the user to root
and nextjs middleware
executes the code as per my needs.
I hope this workaround helps you. ✌️
Workaround for all, Type redirectResponse.headers.set("x-middleware-cache", "no-cache");
to set x-middleware-cache
to no-cache
Middleware isn't running due to cahce. Seems Vercel team is coming up with the fix but anyone can't wait plz check below.
import { type NextMiddlewareResult } from "next/dist/server/web/types";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export const middleware = async (request: NextRequest): Promise<NextMiddlewareResult> => {
const cookieHeader = request.headers.get("cookie");
const cookies = cookieHeader
? Object.fromEntries(cookieHeader.split("; ").map((c) => c.split("=")))
: {};
const accessToken = cookies["accessToken"];
const userType = cookies["userType"];
if (
request.nextUrl.pathname.startsWith("/profile")
) {
if (!accessToken) {
const redirectResponse = NextResponse.redirect(new URL("/login", request.url));
redirectResponse.headers.set("x-middleware-cache", "no-cache"); // Set x-middleware-cache to no-cache
return redirectResponse;
}
}
if (request.nextUrl.pathname.startsWith("/admin")) {
if (userType !== "admin") {
const redirectResponse = NextResponse.redirect(new URL("/", request.url));
redirectResponse.headers.set("x-middleware-cache", "no-cache"); // Set x-middleware-cache to no-cache
return redirectResponse;
}
}
const response = NextResponse.next();
response.headers.set(`x-middleware-cache`, `no-cache`); // Set x-middleware-cache to no-cache
return response;
};
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"],
};
I'm facing a similar issue, where in this middleware :
import { NextRequest, NextResponse } from "next/server"; import unauthorizedRoutes from "./utils/routes"; import evaluateTokensStatus from "./utils/evaluateTokens"; export async function middleware(request: NextRequest) { let tokensStatus = evaluateTokensStatus(); const isAuthenticated = tokensStatus === "valid" || tokensStatus === "expired"; const isUnauthorizedRoute = unauthorizedRoutes.some((route) => request.nextUrl.pathname.startsWith(route) ); console.log("isUnauthorizedRoute", isUnauthorizedRoute); console.log("isAuthenticated", isAuthenticated); if (!isAuthenticated && !isUnauthorizedRoute) { return NextResponse.redirect(new URL("/auth/login", request.url), { status: 303, }); } if (isAuthenticated && isUnauthorizedRoute) { console.log("should redirect to /"); return NextResponse.redirect(new URL("/", request.url), { status: 303, }); } return NextResponse.next(); } export const config = { matcher: ["/((?!api|_next/static|_next/image|.*\\.png$).*)"], };
When redirect should happen it is not working, and nothing happens.
Strange thing ....
I do have a similar issue following the official docs / guide https://nextjs.org/docs/app/building-your-application/authentication#optimistic-checks-with-middleware-optional. The redirect simply does not work as expected.
@lpknv Try disable middleware cache before you return response using
redirectResponse.headers.set("x-middleware-cache", "no-cache");
@lpknv Try disable middleware cache before you return response using
redirectResponse.headers.set("x-middleware-cache", "no-cache");
Thanks, I will give it a try!
@lpknv Did that work? I am having the same issue trying to deploy to a digital ocean server
"x-middleware-cache", "no-cache");
I didn't try it yet. If you are curious you can add redirectResponse.headers.set("x-middleware-cache", "no-cache");
to your middleware. I don't think it has something to do with digital ocean server.
@lpknv unfortunately it didn't work. I belive my issue stems from my SSL certificate which is described here. My SSL guy is sorting it out now.
https://vercel.com/guides/resolve-err-too-many-redirects-when-using-cloudflare-proxy-with-vercel
Edit: it was an SSL issue, as well as an API being redirected to the wrong route which caused a loop during production as the environment variable wasn't set properly
I fixed it with rewrite instead of redirect.
return NextResponse.rewrite(new URL("/login", request.url), { status: 303, });
This might be because your use case only requires server-side. However, this doesn’t actually solve the issue. https://www.dhiwise.com/post/nextjs-rewrites-everything-you-need-to-know
for me the problem was that I was trying to make the middleware cleaner
export async function middleware(request: NextRequest) {
test(request);
return NextResponse.next();
}
function test(request: NextRequest) {
return NextResponse.redirect(new URL('/someroute', request.url))
}
this didn't work until I just squashed everything into middleware function directly
for me the problem was that I was trying to make the middleware cleaner
export async function middleware(request: NextRequest) { test(request); return NextResponse.next(); } function test(request: NextRequest) { return NextResponse.redirect(new URL('/someroute', request.url)) }
this didn't work until I just squashed everything into middleware function directly
I can't recall that in the nextjs docs that you can use Middleware everywhere you want.
`
export default async function middleware(req: NextRequest) {
const publicPathnameRegex = RegExp(
^(/(${locales.join('|')}))?(${publicRoutes .flatMap((p) => (p === '/' ? ['', '/'] : p)) .join('|')})/?$
,
'i',
)
const isPublicPage = publicPathnameRegex.test(req.nextUrl.pathname)
if (isPublicPage) { return intlMiddleware(req) } else { // return (authMiddleware as any)(req)
const token = await getToken({ req, secret: secret })
if (token && Math.floor(Date.now() / 1000) < (token.exp as number)) {
// Token is valid, continue with the request
return intlMiddleware(req)
}
return NextResponse.redirect(`http://localhost:3000`, 303)
} }
export const config = { // Skip all paths that should not be internationalized matcher: ['/((?!api|_next|.\..).*)'], }
`
Still stuck :((, the network tab show the post request to '/' (200 success) but redirect not perform ,
@lubojanski
for me the problem was that I was trying to make the middleware cleaner
export async function middleware(request: NextRequest) { test(request); return NextResponse.next(); } function test(request: NextRequest) { return NextResponse.redirect(new URL('/someroute', request.url)) }
this didn't work until I just squashed everything into middleware function directly
You're not returning your test
function result in the middleware going straight to NextResponse.next()
I'm facing this issue. Any update. I'm using the next.js 15.0.1
Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!
@truongnv98
It probably isn't the same for you, but my issue was a combination of a mistyped environment variable name for the API route and my SSL certificate being invalid so it tried to route to a HTTP version
@truongnv98
It probably isn't the same for you, but my issue was a combination of a mistyped environment variable name for the API route and my SSL certificate being invalid so it tried to route to a HTTP version
"mistyped environment variable name" - I can relate to that haha...
Link to the code that reproduces this issue
https://github.com/anni1236012/nextjsMiddleware
To Reproduce
https://github.com/vercel/next.js/assets/86418669/67bb7e52-b6a3-41c0-b4ad-3eed1eff8404
Current vs. Expected behavior
Delayed navigation, looks like all requests are not reaching middleware and served from cache.
Verify canary release
Provide environment information
Which area(s) are affected? (Select all that apply)
Middleware / Edge (API routes, runtime)
Additional context
No response