middleware.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { type NextRequest, NextResponse } from "next/server";
  2. import ProxyCheck from "proxycheck-ts";
  3. import {
  4. RESTRICTED_MODE_SEGMENT,
  5. VPN_BLOCKED_SEGMENT,
  6. } from "./config/isomorphic";
  7. import { BLOCKED_REGIONS, PROXYCHECK_API_KEY } from "./config/server";
  8. const RESTRICTED_MODE_PATH = `/${RESTRICTED_MODE_SEGMENT}`;
  9. const VPN_BLOCK_PATH = `/${VPN_BLOCKED_SEGMENT}`;
  10. const proxyCheckClient = PROXYCHECK_API_KEY
  11. ? new ProxyCheck({ api_key: PROXYCHECK_API_KEY })
  12. : undefined;
  13. export const middleware = async (request: NextRequest) => {
  14. if (await isProxyBlocked(request)) {
  15. return rewrite(request, VPN_BLOCK_PATH);
  16. } else if (isRegionBlocked(request)) {
  17. return rewrite(request, RESTRICTED_MODE_PATH);
  18. } else if (isBlockedSegment(request)) {
  19. return rewrite(request, "/not-found");
  20. } else {
  21. return;
  22. }
  23. };
  24. const rewrite = (request: NextRequest, path: string) =>
  25. NextResponse.rewrite(new URL(path, request.url));
  26. const isRegionBlocked = ({ geo }: NextRequest) =>
  27. geo?.country !== undefined &&
  28. BLOCKED_REGIONS.includes(geo.country.toLowerCase());
  29. const isProxyBlocked = async ({ ip }: NextRequest) => {
  30. if (proxyCheckClient === undefined || ip === undefined) {
  31. return false;
  32. } else {
  33. const result = await proxyCheckClient.checkIP(ip, { vpn: 2 });
  34. return result[ip]?.proxy === "yes";
  35. }
  36. };
  37. const isBlockedSegment = ({ nextUrl: { pathname } }: NextRequest) =>
  38. pathname.startsWith(`/${VPN_BLOCKED_SEGMENT}`) ||
  39. pathname.startsWith(`/${RESTRICTED_MODE_SEGMENT}`);
  40. export const config = {
  41. // Next.js requires that this is a static string and fails to read it if it's
  42. // a String.raw, so let's disable this rule
  43. // eslint-disable-next-line unicorn/prefer-string-raw
  44. matcher: ["/((?!_next/static|_next/image|api/|terms-of-service|.*\\.).*)"],
  45. };