fix: support Upstash Redis on Cloudflare Pages

This commit is contained in:
Codex
2026-07-20 16:13:51 +08:00
parent 8d558c79cf
commit 27d30139c1
6 changed files with 64 additions and 11 deletions
+19 -2
View File
@@ -3,13 +3,24 @@ import {
authenticateLogin,
createLoginResponse,
getPublicAuthConfig,
ManagedAuthStorageError,
validatePremiumAccess,
} from '@/lib/server/auth';
export const runtime = 'edge';
export async function GET() {
return NextResponse.json(await getPublicAuthConfig());
try {
return NextResponse.json(await getPublicAuthConfig());
} catch (error) {
if (error instanceof ManagedAuthStorageError) {
return NextResponse.json(
{ error: 'Managed authentication storage is unavailable' },
{ status: 503 },
);
}
throw error;
}
}
export async function POST(request: NextRequest) {
@@ -32,7 +43,13 @@ export async function POST(request: NextRequest) {
}
return createLoginResponse(session, request);
} catch {
} catch (error) {
if (error instanceof ManagedAuthStorageError) {
return NextResponse.json(
{ valid: false, message: 'Managed authentication storage is unavailable' },
{ status: 503 },
);
}
return NextResponse.json({ valid: false, message: 'Invalid request' }, { status: 400 });
}
}
+16 -2
View File
@@ -1,10 +1,24 @@
import { NextRequest } from 'next/server';
import { createSessionStatusResponse, logoutResponse } from '@/lib/server/auth';
import {
createSessionStatusResponse,
logoutResponse,
ManagedAuthStorageError,
} from '@/lib/server/auth';
export const runtime = 'edge';
export async function GET(request: NextRequest) {
return createSessionStatusResponse(request);
try {
return await createSessionStatusResponse(request);
} catch (error) {
if (error instanceof ManagedAuthStorageError) {
return Response.json(
{ authenticated: false, error: 'Managed authentication storage is unavailable' },
{ status: 503 },
);
}
throw error;
}
}
export async function DELETE(request: NextRequest) {
+1 -1
View File
@@ -5,7 +5,7 @@
* so they persist across browsers, devices, and PWA installs.
*/
import { Redis } from '@upstash/redis';
import { Redis } from '@upstash/redis/cloudflare';
import { NextRequest, NextResponse } from 'next/server';
import { authenticationRequiredResponse } from '@/lib/server/api-responses';
import { getServerSession } from '@/lib/server/auth';
+1 -1
View File
@@ -1,4 +1,4 @@
import { Redis } from '@upstash/redis';
import { Redis } from '@upstash/redis/cloudflare';
import { NextRequest, NextResponse } from 'next/server';
import { authenticationRequiredResponse } from '@/lib/server/api-responses';
import { getServerSession } from '@/lib/server/auth';
+6
View File
@@ -207,6 +207,12 @@ export function PasswordGate({
});
const data = await response.json();
if (response.status === 503) {
setError('认证存储暂时不可用,请检查 Upstash Redis 配置');
setIsValidating(false);
return;
}
if (data.valid && data.session) {
setSession(toAuthSession(data.session), data.persistSession ?? persistSession);
setIsLocked(false);
+21 -5
View File
@@ -1,4 +1,4 @@
import { Redis } from '@upstash/redis';
import { Redis } from '@upstash/redis/cloudflare';
import { NextRequest, NextResponse } from 'next/server';
import { getRuntimeFeatures } from '@/lib/server/runtime-features';
import {
@@ -89,6 +89,13 @@ const effectiveAdminPassword = ADMIN_PASSWORD || ACCESS_PASSWORD;
let cachedRedis: Redis | null | undefined;
export class ManagedAuthStorageError extends Error {
constructor(operation: 'read' | 'write', cause?: unknown) {
super(`Managed auth storage ${operation} failed`, { cause });
this.name = 'ManagedAuthStorageError';
}
}
function getRedisClient(): Redis | null {
if (cachedRedis !== undefined) {
return cachedRedis;
@@ -99,7 +106,10 @@ function getRedisClient(): Redis | null {
return cachedRedis;
}
cachedRedis = Redis.fromEnv();
cachedRedis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL,
token: process.env.UPSTASH_REDIS_REST_TOKEN,
});
return cachedRedis;
}
@@ -140,8 +150,9 @@ async function readManagedAccounts(): Promise<StoredAccountRecord[]> {
const stored = await redis.get(MANAGED_ACCOUNTS_KEY);
if (!Array.isArray(stored)) return [];
return stored.filter(isStoredAccountRecord).map(normalizeStoredAccount);
} catch {
return [];
} catch (error) {
console.error('Managed auth Redis read failed:', error);
throw new ManagedAuthStorageError('read', error);
}
}
@@ -151,7 +162,12 @@ async function saveManagedAccounts(accounts: StoredAccountRecord[]): Promise<voi
throw new Error('Managed auth storage unavailable');
}
await redis.set(MANAGED_ACCOUNTS_KEY, accounts);
try {
await redis.set(MANAGED_ACCOUNTS_KEY, accounts);
} catch (error) {
console.error('Managed auth Redis write failed:', error);
throw new ManagedAuthStorageError('write', error);
}
}
function getBootstrapSeeds(): SeedAccountInput[] {