优化 Vercel Fluid CPU:API加CDN缓存、缩小middleware范围、跳过公共API的Supabase身份转发
- 7条GET路由加 s-maxage + stale-while-revalidate,fetch 改为 next revalidate - middleware matcher 从全匹配缩小到9条需auth的路径,移除 isStaticAsset - 8条公共API路由加 includeSupabaseIdentity: false - backend-auth getSession 为空时跳过 getUser - subscription-help 加 I18nProvider,移除 force-dynamic → 静态预渲染 - next.config.mjs 加静态资源 immutable 缓存头 Tested: npx tsc --noEmit 通过,npm run build 通过
This commit is contained in:
@@ -26,7 +26,9 @@ export async function POST(req: NextRequest) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const body = await req.json();
|
const body = await req.json();
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const headers = new Headers(auth.headers);
|
const headers = new Headers(auth.headers);
|
||||||
headers.set("Content-Type", "application/json");
|
headers.set("Content-Type", "application/json");
|
||||||
const res = await fetch(`${API_BASE}/api/analytics/events`, {
|
const res = await fetch(`${API_BASE}/api/analytics/events`, {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
export const dynamic = "force-dynamic";
|
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
if (!API_BASE) {
|
if (!API_BASE) {
|
||||||
@@ -27,7 +26,7 @@ export async function GET(req: NextRequest) {
|
|||||||
});
|
});
|
||||||
const res = await fetch(`${API_BASE}/api/cities`, {
|
const res = await fetch(`${API_BASE}/api/cities`, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 60 },
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
@@ -38,7 +37,7 @@ export async function GET(req: NextRequest) {
|
|||||||
const response = buildCachedJsonResponse(
|
const response = buildCachedJsonResponse(
|
||||||
req,
|
req,
|
||||||
data,
|
data,
|
||||||
"no-store, max-age=0",
|
"public, max-age=0, s-maxage=60, stale-while-revalidate=300",
|
||||||
);
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
buildProxyExceptionResponse,
|
buildProxyExceptionResponse,
|
||||||
buildUpstreamErrorResponse,
|
buildUpstreamErrorResponse,
|
||||||
} from "@/lib/api-proxy";
|
} from "@/lib/api-proxy";
|
||||||
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
|
|
||||||
@@ -42,10 +43,12 @@ export async function GET(
|
|||||||
const url = `${API_BASE}/api/city/${encodeURIComponent(name)}/detail?${searchParams.toString()}`;
|
const url = `${API_BASE}/api/city/${encodeURIComponent(name)}/detail?${searchParams.toString()}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 15 },
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
@@ -53,7 +56,11 @@ export async function GET(
|
|||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const response = NextResponse.json(data);
|
const response = buildCachedJsonResponse(
|
||||||
|
req,
|
||||||
|
data,
|
||||||
|
"public, max-age=0, s-maxage=15, stale-while-revalidate=45",
|
||||||
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const response = buildProxyExceptionResponse(error, {
|
const response = buildProxyExceptionResponse(error, {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
buildProxyExceptionResponse,
|
buildProxyExceptionResponse,
|
||||||
buildUpstreamErrorResponse,
|
buildUpstreamErrorResponse,
|
||||||
} from "@/lib/api-proxy";
|
} from "@/lib/api-proxy";
|
||||||
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
|
|
||||||
@@ -45,10 +46,12 @@ export async function GET(
|
|||||||
const url = `${API_BASE}/api/city/${encodeURIComponent(name)}/market-scan?${params.toString()}`;
|
const url = `${API_BASE}/api/city/${encodeURIComponent(name)}/market-scan?${params.toString()}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 20 },
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
@@ -59,11 +62,11 @@ export async function GET(
|
|||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const response = NextResponse.json(data, {
|
const response = buildCachedJsonResponse(
|
||||||
headers: {
|
req,
|
||||||
"Cache-Control": "no-store",
|
data,
|
||||||
},
|
"public, max-age=0, s-maxage=20, stale-while-revalidate=60",
|
||||||
});
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const response = buildProxyExceptionResponse(error, {
|
const response = buildProxyExceptionResponse(error, {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
buildProxyExceptionResponse,
|
buildProxyExceptionResponse,
|
||||||
buildUpstreamErrorResponse,
|
buildUpstreamErrorResponse,
|
||||||
} from "@/lib/api-proxy";
|
} from "@/lib/api-proxy";
|
||||||
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
|
|
||||||
@@ -131,26 +132,28 @@ export async function GET(
|
|||||||
const url = `${API_BASE}/api/city/${encodeURIComponent(name)}?force_refresh=${forceRefresh}&depth=${encodeURIComponent(depth)}`;
|
const url = `${API_BASE}/api/city/${encodeURIComponent(name)}?force_refresh=${forceRefresh}&depth=${encodeURIComponent(depth)}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 15 },
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
const summaryUrl = `${API_BASE}/api/city/${encodeURIComponent(name)}/summary?force_refresh=${forceRefresh}`;
|
const summaryUrl = `${API_BASE}/api/city/${encodeURIComponent(name)}/summary?force_refresh=${forceRefresh}`;
|
||||||
const summaryRes = await fetch(summaryUrl, {
|
const summaryRes = await fetch(summaryUrl, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 10 },
|
||||||
});
|
});
|
||||||
if (summaryRes.ok) {
|
if (summaryRes.ok) {
|
||||||
const summaryData = await summaryRes.json();
|
const summaryData = await summaryRes.json();
|
||||||
const response = NextResponse.json(buildFallbackCityDetail(name, depth, summaryData), {
|
const response = buildCachedJsonResponse(
|
||||||
headers: {
|
req,
|
||||||
"Cache-Control": "no-store",
|
buildFallbackCityDetail(name, depth, summaryData),
|
||||||
"X-PolyWeather-Fallback": "summary",
|
"public, max-age=0, s-maxage=10, stale-while-revalidate=30",
|
||||||
},
|
);
|
||||||
});
|
response.headers.set("X-PolyWeather-Fallback", "summary");
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +161,11 @@ export async function GET(
|
|||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
}
|
}
|
||||||
const data = normalizeCityDetailPayload(await res.json());
|
const data = normalizeCityDetailPayload(await res.json());
|
||||||
const response = NextResponse.json(data);
|
const response = buildCachedJsonResponse(
|
||||||
|
req,
|
||||||
|
data,
|
||||||
|
"public, max-age=0, s-maxage=15, stale-while-revalidate=45",
|
||||||
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const response = buildProxyExceptionResponse(error, {
|
const response = buildProxyExceptionResponse(error, {
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ export async function GET(
|
|||||||
const url = `${API_BASE}/api/history/${encodeURIComponent(name)}`;
|
const url = `${API_BASE}/api/history/${encodeURIComponent(name)}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const fetchOptions = {
|
const fetchOptions = {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
next: { revalidate: 60 },
|
next: { revalidate: 60 },
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
buildProxyExceptionResponse,
|
buildProxyExceptionResponse,
|
||||||
buildUpstreamErrorResponse,
|
buildUpstreamErrorResponse,
|
||||||
} from "@/lib/api-proxy";
|
} from "@/lib/api-proxy";
|
||||||
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ export async function GET(req: NextRequest) {
|
|||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req);
|
||||||
const res = await fetch(`${API_BASE}/api/payments/config`, {
|
const res = await fetch(`${API_BASE}/api/payments/config`, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 300 },
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
@@ -31,9 +32,11 @@ export async function GET(req: NextRequest) {
|
|||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const response = NextResponse.json(data, {
|
const response = buildCachedJsonResponse(
|
||||||
headers: { "Cache-Control": "no-store" },
|
req,
|
||||||
});
|
data,
|
||||||
|
"public, max-age=0, s-maxage=300, stale-while-revalidate=900",
|
||||||
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return buildProxyExceptionResponse(error, {
|
return buildProxyExceptionResponse(error, {
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import {
|
|||||||
buildProxyExceptionResponse,
|
buildProxyExceptionResponse,
|
||||||
buildUpstreamErrorResponse,
|
buildUpstreamErrorResponse,
|
||||||
} from "@/lib/api-proxy";
|
} from "@/lib/api-proxy";
|
||||||
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
const SCAN_TERMINAL_PROXY_TIMEOUT_MS = Number(
|
const SCAN_TERMINAL_PROXY_TIMEOUT_MS = Number(
|
||||||
process.env.POLYWEATHER_SCAN_TERMINAL_PROXY_TIMEOUT_MS || "28000",
|
process.env.POLYWEATHER_SCAN_TERMINAL_PROXY_TIMEOUT_MS || "28000",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
|
||||||
export const maxDuration = 30;
|
export const maxDuration = 30;
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
@@ -50,10 +50,12 @@ export async function GET(req: NextRequest) {
|
|||||||
const timeoutId = setTimeout(() => controller.abort(), SCAN_TERMINAL_PROXY_TIMEOUT_MS);
|
const timeoutId = setTimeout(() => controller.abort(), SCAN_TERMINAL_PROXY_TIMEOUT_MS);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auth = await buildBackendRequestHeaders(req);
|
auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 10 },
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -62,11 +64,11 @@ export async function GET(req: NextRequest) {
|
|||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const response = NextResponse.json(data, {
|
const response = buildCachedJsonResponse(
|
||||||
headers: {
|
req,
|
||||||
"Cache-Control": "no-store",
|
data,
|
||||||
},
|
"public, max-age=0, s-maxage=10, stale-while-revalidate=30",
|
||||||
});
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const timedOut = controller.signal.aborted;
|
const timedOut = controller.signal.aborted;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
buildProxyExceptionResponse,
|
buildProxyExceptionResponse,
|
||||||
buildUpstreamErrorResponse,
|
buildUpstreamErrorResponse,
|
||||||
} from "@/lib/api-proxy";
|
} from "@/lib/api-proxy";
|
||||||
|
import { buildCachedJsonResponse } from "@/lib/http-cache";
|
||||||
|
|
||||||
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
|
||||||
|
|
||||||
@@ -19,10 +20,12 @@ export async function GET(req: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req, {
|
||||||
|
includeSupabaseIdentity: false,
|
||||||
|
});
|
||||||
const res = await fetch(`${API_BASE}/api/system/status`, {
|
const res = await fetch(`${API_BASE}/api/system/status`, {
|
||||||
headers: auth.headers,
|
headers: auth.headers,
|
||||||
cache: "no-store",
|
next: { revalidate: 30 },
|
||||||
});
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
@@ -33,9 +36,11 @@ export async function GET(req: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const response = NextResponse.json(data, {
|
const response = buildCachedJsonResponse(
|
||||||
headers: { "Cache-Control": "no-store" },
|
req,
|
||||||
});
|
data,
|
||||||
|
"public, max-age=0, s-maxage=30, stale-while-revalidate=120",
|
||||||
|
);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return buildProxyExceptionResponse(error, {
|
return buildProxyExceptionResponse(error, {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { SubscriptionHelpClient } from "./SubscriptionHelpClient";
|
import { SubscriptionHelpClient } from "./SubscriptionHelpClient";
|
||||||
|
import { I18nProvider } from "@/hooks/useI18n";
|
||||||
export const dynamic = "force-dynamic";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "PolyWeather | Subscription Help",
|
title: "PolyWeather | Subscription Help",
|
||||||
@@ -9,5 +8,9 @@ export const metadata: Metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function SubscriptionHelpPage() {
|
export default function SubscriptionHelpPage() {
|
||||||
return <SubscriptionHelpClient />;
|
return (
|
||||||
|
<I18nProvider>
|
||||||
|
<SubscriptionHelpClient />
|
||||||
|
</I18nProvider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,17 +41,21 @@ export async function buildBackendRequestHeaders(
|
|||||||
const incomingAuth = extractBearerToken(request.headers.get("authorization"));
|
const incomingAuth = extractBearerToken(request.headers.get("authorization"));
|
||||||
const includeSupabaseIdentity = options?.includeSupabaseIdentity !== false;
|
const includeSupabaseIdentity = options?.includeSupabaseIdentity !== false;
|
||||||
if (hasSupabaseServerEnv() && includeSupabaseIdentity) {
|
if (hasSupabaseServerEnv() && includeSupabaseIdentity) {
|
||||||
const passthroughResponse = new NextResponse(null, { status: 200 });
|
const supabase = createSupabaseRouteClient(request, new NextResponse(null, { status: 200 }));
|
||||||
const supabase = createSupabaseRouteClient(request, passthroughResponse);
|
|
||||||
const {
|
const {
|
||||||
data: { session },
|
data: { session },
|
||||||
} = await supabase.auth.getSession();
|
} = await supabase.auth.getSession();
|
||||||
const {
|
let user = session?.user ?? null;
|
||||||
data: { user },
|
if (session) {
|
||||||
} = await supabase.auth.getUser();
|
const {
|
||||||
|
data: { user: validated },
|
||||||
|
} = await supabase.auth.getUser();
|
||||||
|
user = validated ?? session.user;
|
||||||
|
}
|
||||||
|
|
||||||
const forwardedUserId = String(user?.id || session?.user?.id || "").trim();
|
const passthroughResponse = new NextResponse(null, { status: 200 });
|
||||||
const forwardedEmail = String(user?.email || session?.user?.email || "").trim();
|
const forwardedUserId = String(user?.id || "").trim();
|
||||||
|
const forwardedEmail = String(user?.email || "").trim();
|
||||||
if (forwardedUserId) {
|
if (forwardedUserId) {
|
||||||
headers.set(FORWARDED_SUPABASE_USER_ID_HEADER, forwardedUserId);
|
headers.set(FORWARDED_SUPABASE_USER_ID_HEADER, forwardedUserId);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-23
@@ -20,23 +20,6 @@ const SUPABASE_AUTH_REQUIRED = readEnvBool(
|
|||||||
SUPABASE_AUTH_ENABLED,
|
SUPABASE_AUTH_ENABLED,
|
||||||
);
|
);
|
||||||
|
|
||||||
function isStaticAsset(pathname: string) {
|
|
||||||
return (
|
|
||||||
pathname.startsWith("/_next/") ||
|
|
||||||
pathname.startsWith("/favicon") ||
|
|
||||||
pathname === "/apple-touch-icon.png" ||
|
|
||||||
pathname === "/manifest.webmanifest" ||
|
|
||||||
pathname === "/site.webmanifest" ||
|
|
||||||
pathname.startsWith("/android-chrome-") ||
|
|
||||||
pathname.startsWith("/robots.txt") ||
|
|
||||||
pathname.startsWith("/sitemap.xml") ||
|
|
||||||
pathname.startsWith("/icons/") ||
|
|
||||||
pathname.startsWith("/images/") ||
|
|
||||||
pathname.startsWith("/scenery/") ||
|
|
||||||
pathname.startsWith("/static/")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isPublicPage(pathname: string) {
|
function isPublicPage(pathname: string) {
|
||||||
return (
|
return (
|
||||||
pathname === "/" ||
|
pathname === "/" ||
|
||||||
@@ -78,7 +61,7 @@ function handleLegacyTokenGate(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { pathname, searchParams } = request.nextUrl;
|
const { pathname, searchParams } = request.nextUrl;
|
||||||
if (isStaticAsset(pathname) || isPublicPage(pathname) || isPublicApi(pathname)) {
|
if (isPublicPage(pathname) || isPublicApi(pathname)) {
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,10 +161,6 @@ async function handleSupabaseOptionalSession(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function middleware(request: NextRequest) {
|
export async function middleware(request: NextRequest) {
|
||||||
const { pathname } = request.nextUrl;
|
|
||||||
if (isStaticAsset(pathname)) {
|
|
||||||
return NextResponse.next();
|
|
||||||
}
|
|
||||||
const requestHost =
|
const requestHost =
|
||||||
request.headers.get("x-forwarded-host") ||
|
request.headers.get("x-forwarded-host") ||
|
||||||
request.headers.get("host") ||
|
request.headers.get("host") ||
|
||||||
@@ -203,5 +182,15 @@ export async function middleware(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: ["/((?!_next/static|_next/image).*)"],
|
matcher: [
|
||||||
|
"/account/:path*",
|
||||||
|
"/ops/:path*",
|
||||||
|
"/api/auth/:path*",
|
||||||
|
"/api/ops/:path*",
|
||||||
|
"/api/payments/:path*",
|
||||||
|
"/api/system/:path*",
|
||||||
|
"/api/history/:path*",
|
||||||
|
"/api/city/:path*/detail:path*",
|
||||||
|
"/api/scan/terminal/ai:path*",
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
async headers() {
|
||||||
|
const cacheHeader = {
|
||||||
|
key: "Cache-Control",
|
||||||
|
value: "public, max-age=31536000, immutable",
|
||||||
|
};
|
||||||
|
const staticExts = ["jpg", "jpeg", "png", "gif", "ico", "svg", "webp", "avif", "woff2", "ttf", "eot", "css", "js"];
|
||||||
|
return staticExts.map((ext) => ({
|
||||||
|
source: `/:path(.+\\.${ext})`,
|
||||||
|
headers: [cacheHeader],
|
||||||
|
}));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
Reference in New Issue
Block a user