generated from rajput-hemant/nextjs-template
-
Notifications
You must be signed in to change notification settings - Fork 22
/
middleware.ts
100 lines (83 loc) · 2.77 KB
/
middleware.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { NextResponse } from "next/server";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
import NextAuth from "next-auth";
import type { NextRequest } from "next/server";
import { authConfig } from "./config/auth";
import {
authRoutes,
DEFAULT_LOGIN_REDIRECT,
publicRoutes,
} from "./config/routes";
import { env } from "./lib/env";
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(env.RATE_LIMITING_REQUESTS_PER_SECOND, "1s"),
});
const { auth } = NextAuth(authConfig);
export default auth(async (req) => {
/* -----------------------------------------------------------------------------------------------
* Rate limiting middleware
* -----------------------------------------------------------------------------------------------*/
if (env.ENABLE_RATE_LIMITING === "true" && env.NODE_ENV === "production") {
const id = getIP(req) || "anonymous";
const { limit, pending, remaining, reset, success } =
await ratelimit.limit(id);
if (!success) {
return NextResponse.json(
{
error: {
message: "Too many requests",
limit,
pending,
remaining,
reset: `${reset - Date.now()}ms`,
},
},
{
status: 429,
headers: {
"x-ratelimit-limit": limit.toString(),
"x-ratelimit-remaining": remaining.toString(),
},
}
);
}
}
/* -----------------------------------------------------------------------------------------------
* Authentication middleware
* -----------------------------------------------------------------------------------------------*/
const { nextUrl } = req;
const isLoggedIn = !!req.auth;
const isAuthRoute = authRoutes.includes(nextUrl.pathname);
const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
if (isAuthRoute) {
if (isLoggedIn) {
return NextResponse.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
}
return NextResponse.next();
}
if (!isLoggedIn && !isPublicRoute) {
let from = nextUrl.pathname;
if (nextUrl.search) {
from += nextUrl.search;
}
return NextResponse.redirect(
new URL(`/login?from=${encodeURIComponent(from)}`, nextUrl)
);
}
return NextResponse.next();
});
export const config = {
// match all routes except static files, _next and api/auth
matcher: ["/((?!.+\\.[\\w]+$|_next|api/auth).*)"],
};
function getIP(req: NextRequest): string {
// @ts-expect-error ip is not available in NextRequest
let ip = req.ip ?? req.headers.get("x-real-ip");
const forwardedFor = req.headers.get("x-forwarded-for");
if (!ip && forwardedFor) {
ip = forwardedFor.split(",").at(0) ?? "";
}
return ip;
}