Since Next.js v12, there is something called "middleware". It is a unique file that acts as a middleware between the server and the client. Here is my implementation in TypeScript:
import { NextRequest, NextResponse } from "next/server";
type Environment = "production" | "development" | "other";
export function middleware(request: NextRequest) {
const currentEnv = process.env.NODE_ENV as Environment;
const isLocalhost = request.headers.get("host")?.includes("localhost");
const isProtocolHTTP = request.headers.get("x-forwarded-proto") === "http";
if (currentEnv === "production" && !isLocalhost && isProtocolHTTP) {
return NextResponse.redirect(
`https://${request.headers.get("host")}${request.nextUrl.pathname}${
request?.nextUrl?.search || ""
}`,
301,
);
}
}
export const config = {
matcher: ["/*"],
};
For Next.js 13, we will need to use this code:
import { NextRequest, NextResponse } from "next/server";
type Environment = "production" | "development" | "other";
export function middleware(request: NextRequest) {
const headers = new Headers(request.headers);
const currentEnv = process.env.NODE_ENV as Environment;
const isHttps = headers.get("x-forwarded-proto")?.split(",")[0] === "https";
const isLocalhost = request.headers.get("host")?.includes("localhost");
if (currentEnv === "production" && !isHttps && !isLocalhost) {
const newUrl = new URL(`http://${headers.get("host")}` || "");
newUrl.protocol = "https:";
return NextResponse.redirect(newUrl.href, 301);
}
}
Create a new file named "middleware.ts" in the root path, then all the magic will happen automatically.
I think the code speaks by itself, but here is a short explanation:
We check if the environment is production, if we're not on localhost and if the protocol is HTTP. If it is, we redirect the user to the same URL without the HTTP, then we add the HTTPs to the URL.
This works perfectly and I use it in a lot of projects, also in Heroku.