I get a 404 error every time I make the first request to my app homepage. It will work after a simple refresh.
Steps to reproduce:
Access https://www.zaptube.vip or curl -I https://www.zaptube.vip
curl -I https://www.zaptube.vip
HTTP/2 404
accept-ranges: bytes
access-control-allow-origin: *
age: 119
cache-control: public, max-age=0, must-revalidate
content-disposition: inline; filename="404"
content-type: text/html; charset=utf-8
date: Wed, 08 Jan 2025 14:09:49 GMT
etag: "d3503f134747dd752bf9b78f170299cb"
last-modified: Wed, 08 Jan 2025 14:07:50 GMT
server: Vercel
set-cookie: locale=en; Path=/
strict-transport-security: max-age=63072000
x-matched-path: /404
x-vercel-cache: HIT
x-vercel-id: gru1::fjlft-1736345389516-af4b261091a4
content-length: 5939
In the logs I see the 404s related to requests to the /wordpress/wp-admin/setup-config.php
and /wp-admin/setup-config.php
endpoints (I’m not sure what are those)
I’ve tried some workarounds without success
This is the [locale]/[slug] page:
import { redirect } from "next/navigation";
import { ChannelService } from "@/app/services/channel.service";
import SubscribePage from "@/app/[locale]/subscribe/[slug]/page";
export default async function ChannelPage({
params,
}: {
params: { slug: string };
}) {
const channelService = new ChannelService();
let decodedSlug = decodeURIComponent(params.slug);
if (decodedSlug.includes("wp-admin") || decodedSlug.includes("setup-config.php")) {
console.warn(`[ChannelPage] Invalid slug: ${decodedSlug}`);
return redirect("/");
}
// all slugs should start with @ in the db, we will allow the user to not include it in the url
if (!decodedSlug.startsWith("@")) {
decodedSlug = `@${decodedSlug}`;
}
const channel = await channelService.getChannel({ slug: decodedSlug }, {});
if (!channel) {
console.warn(`[ChannelPage] Channel not found: ${decodedSlug}`);
return redirect("/");
}
if (channel?.defaultLocale) {
redirect(`/${channel.defaultLocale}/subscribe/${decodedSlug}`);
}
return <SubscribePage params={{ slug: decodedSlug }} />;
}
This is how my middleware is configured:
import createMiddleware from "next-intl/middleware";
import { NextRequest, NextResponse } from "next/server";
import { withAuth } from "next-auth/middleware";
import { locales, defaultLocale } from "@/app/i18n/settings";
const intlMiddleware = createMiddleware({
locales,
defaultLocale,
localePrefix: "never", // Prevent locales in the URL
});
const authMiddleware = withAuth(
function middleware(req) {
if (
req.nextUrl.pathname.startsWith("/admin") &&
req.nextauth.token === null
) {
return NextResponse.redirect(
new URL(`/login?callbackUrl=${encodeURIComponent(req.url)}`, req.url)
);
}
return NextResponse.next(); // Proceed if authenticated
},
{
callbacks: {
authorized: ({ token }) => !!token,
},
}
);
export default function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
console.log(`[Middleware] Requested path: ${pathname}`);
// Block invalid paths early
const blockedPatterns = ["wp-admin", "setup-config.php"];
if (blockedPatterns.some((pattern) => pathname.includes(pattern))) {
console.warn(`[Middleware] Blocked invalid path: ${pathname}`);
// Initialize `next-intl` before redirecting
intlMiddleware(request);
return NextResponse.redirect(new URL("/", request.url));
}
const localeCookie = request.cookies.get("locale");
// Admin route logic
if (pathname.startsWith("/admin")) {
const response = authMiddleware(request as any, {} as any);
if (!localeCookie) {
const preferredLocale =
request.headers.get("accept-language")?.split(",")[0].split("-")[0] ||
defaultLocale;
if (response instanceof NextResponse) {
response.cookies.set("locale", preferredLocale, { path: "/" });
return response;
}
}
return intlMiddleware(request);
}
// Set locale cookie if not already set
if (!localeCookie) {
const preferredLocale =
request.headers.get("accept-language")?.split(",")[0].split("-")[0] ||
defaultLocale;
const response = NextResponse.next();
response.cookies.set("locale", preferredLocale, { path: "/" });
return response;
}
// Ensure intlMiddleware runs for all other requests
return intlMiddleware(request);
}
export const config = {
matcher: ["/((?!api|_next).*)"],
methods: ["GET", "HEAD"],
};