Extras
Rate Limits (API Calls)
To prevent abuse, it’s recommended to limit the number of API calls a user can perform in a given time frame based on their IP address. In this example, we’ll be limiting it to 5 API calls per minute using Upstash.
You can find an example of how the middleware.ts
file should look like at the end of this
page.
-
Login to your Upstash account or create a new one [here].
-
Create a new Redis database.
-
In the
DETAILS
section of the database, copy theUPSTASH_REDIS_REST_URL
andUPSTASH_REDIS_REST_TOKEN
-
Update the following variables inside the
.env.local
in the codebase:
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
- In the codebase, run the following command to install the
@upstash/ratelimit
package:
npm install @upstash/redis @upstash/ratelimit
- In the
middleware.ts
file, add theRATE_LIMITED_URLS
array outside of the middleware function. This array contains the URLs that will be rate limited. You can add more URLs to the array if you want to rate limit more endpoints.
const RATE_LIMITED_URLS = ["/api/example-call"];
- In the
middleware.ts
file, add theredis
client with theUPSTASH_REDIS_REST_URL
andUPSTASH_REDIS_REST_TOKEN
outside of the middleware function:
const redis = new Redis({
url: process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL,
token: process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN,
});
- In the
middleware.ts
file, add therateLimit
outside of the middleware function. In our case, we’ll be limiting it to 5 API calls per minute (60 seconds). If a user makes more than 5 API calls in a minute, they will receive a429 Too Many Requests
response.
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.slidingWindow(5, "60 s"),
});
- In the
middleware.ts
file, add function to check if the URL is rate limited and return the appropriate response.
if (RATE_LIMITED_URLS.some((url) => request.nextUrl.pathname.startsWith(url))) {
const ip = request.ip ?? "127.0.0.1";
const { success } = await ratelimit.limit(ip);
if (!success) {
return new nextResponse("Too Many Requests", { status: 429 });
}
}
Please add this if statement inside the middleware function BUT before the handleRedirection
function. Otherwise, the rate limit will not work as it will be executed after the API call has
been made.
Here’s an example of how the middleware.ts
file should look like:
import { Redis } from "@upstash/redis";
import { Ratelimit } from "@upstash/ratelimit";
const RATE_LIMITED_URLS = ["/api/example-call"];
...
const redis = new Redis({
url: process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL,
token: process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN,
});
const ratelimit = new Ratelimit({
redis: redis,
limiter: Ratelimit.slidingWindow(5, "60 s"),
});
export const middleware = async (request: nextRequest) => {
...
const {
data: { user },
} = await supabaseClient.auth.getUser();
if (RATE_LIMITED_URLS.some((url) => request.nextUrl.pathname.startsWith(url))) {
const ip = request.ip ?? "127.0.0.1";
const { success } = await ratelimit.limit(ip);
if (!success) {
return new nextResponse("Too Many Requests", { status: 429 });
}
}
const routingResponse = await handleRedirection({ request, user });
if (routingResponse) return routingResponse;
...
};