Harden auth profile fallback for slow backend responses
This commit is contained in:
@@ -16,10 +16,18 @@ export async function GET(req: NextRequest) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await buildBackendRequestHeaders(req);
|
const auth = await buildBackendRequestHeaders(req);
|
||||||
const res = await fetch(`${API_BASE}/api/auth/me`, {
|
const controller = new AbortController();
|
||||||
headers: auth.headers,
|
const timeoutId = setTimeout(() => controller.abort(), 6000);
|
||||||
cache: "no-store",
|
let res: Response;
|
||||||
});
|
try {
|
||||||
|
res = await fetch(`${API_BASE}/api/auth/me`, {
|
||||||
|
headers: auth.headers,
|
||||||
|
cache: "no-store",
|
||||||
|
signal: controller.signal,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
if (res.status === 401 || res.status === 403) {
|
if (res.status === 401 || res.status === 403) {
|
||||||
const response = NextResponse.json({
|
const response = NextResponse.json({
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
@@ -30,6 +38,23 @@ export async function GET(req: NextRequest) {
|
|||||||
}
|
}
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const raw = await res.text();
|
const raw = await res.text();
|
||||||
|
if (auth.authUserId) {
|
||||||
|
const response = NextResponse.json({
|
||||||
|
authenticated: true,
|
||||||
|
user_id: auth.authUserId,
|
||||||
|
email: auth.authEmail || null,
|
||||||
|
subscription_active: null,
|
||||||
|
subscription_plan_code: null,
|
||||||
|
subscription_expires_at: null,
|
||||||
|
subscription_total_expires_at: null,
|
||||||
|
subscription_queued_days: 0,
|
||||||
|
subscription_queued_count: 0,
|
||||||
|
points: 0,
|
||||||
|
degraded_auth_profile: true,
|
||||||
|
degraded_reason: `backend_${res.status}`,
|
||||||
|
});
|
||||||
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
|
}
|
||||||
const response = NextResponse.json(
|
const response = NextResponse.json(
|
||||||
{ error: `Backend returned ${res.status}`, detail: raw.slice(0, 300) },
|
{ error: `Backend returned ${res.status}`, detail: raw.slice(0, 300) },
|
||||||
{ status: res.status },
|
{ status: res.status },
|
||||||
@@ -40,9 +65,28 @@ export async function GET(req: NextRequest) {
|
|||||||
const response = NextResponse.json(data);
|
const response = NextResponse.json(data);
|
||||||
return applyAuthResponseCookies(response, auth.response);
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const auth = await buildBackendRequestHeaders(req);
|
||||||
|
if (auth.authUserId) {
|
||||||
|
const response = NextResponse.json({
|
||||||
|
authenticated: true,
|
||||||
|
user_id: auth.authUserId,
|
||||||
|
email: auth.authEmail || null,
|
||||||
|
subscription_active: null,
|
||||||
|
subscription_plan_code: null,
|
||||||
|
subscription_expires_at: null,
|
||||||
|
subscription_total_expires_at: null,
|
||||||
|
subscription_queued_days: 0,
|
||||||
|
subscription_queued_count: 0,
|
||||||
|
points: 0,
|
||||||
|
degraded_auth_profile: true,
|
||||||
|
degraded_reason: String(error),
|
||||||
|
});
|
||||||
|
return applyAuthResponseCookies(response, auth.response);
|
||||||
|
}
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Failed to fetch auth profile", detail: String(error) },
|
{ error: "Failed to fetch auth profile", detail: String(error) },
|
||||||
{ status: 500 },
|
{ status: 500 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ export const FORWARDED_SUPABASE_EMAIL_HEADER = "x-polyweather-auth-email";
|
|||||||
type HeaderBuildResult = {
|
type HeaderBuildResult = {
|
||||||
headers: HeadersInit;
|
headers: HeadersInit;
|
||||||
response: NextResponse | null;
|
response: NextResponse | null;
|
||||||
|
authUserId?: string | null;
|
||||||
|
authEmail?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
type HeaderBuildOptions = {
|
type HeaderBuildOptions = {
|
||||||
@@ -59,20 +61,20 @@ export async function buildBackendRequestHeaders(
|
|||||||
|
|
||||||
if (incomingAuth) {
|
if (incomingAuth) {
|
||||||
headers.set("Authorization", `Bearer ${incomingAuth}`);
|
headers.set("Authorization", `Bearer ${incomingAuth}`);
|
||||||
return { headers, response: passthroughResponse };
|
return { headers, response: passthroughResponse, authUserId: forwardedUserId || null, authEmail: forwardedEmail || null };
|
||||||
}
|
}
|
||||||
const accessToken = session?.access_token || "";
|
const accessToken = session?.access_token || "";
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
// Fallback to cookie-backed session when request does not carry bearer.
|
// Fallback to cookie-backed session when request does not carry bearer.
|
||||||
headers.set("Authorization", `Bearer ${accessToken}`);
|
headers.set("Authorization", `Bearer ${accessToken}`);
|
||||||
}
|
}
|
||||||
return { headers, response: passthroughResponse };
|
return { headers, response: passthroughResponse, authUserId: forwardedUserId || null, authEmail: forwardedEmail || null };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incomingAuth) {
|
if (incomingAuth) {
|
||||||
headers.set("Authorization", `Bearer ${incomingAuth}`);
|
headers.set("Authorization", `Bearer ${incomingAuth}`);
|
||||||
}
|
}
|
||||||
return { headers, response: null };
|
return { headers, response: null, authUserId: null, authEmail: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applyAuthResponseCookies(
|
export function applyAuthResponseCookies(
|
||||||
@@ -87,3 +89,5 @@ export function applyAuthResponseCookies(
|
|||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user