fix: improve error handling for swapper and upload APIs
This commit is contained in:
@@ -7,24 +7,54 @@ const CITY_SERVICE_URL =
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const formData = await request.formData();
|
||||
// Read the original form data
|
||||
const incomingFormData = await request.formData();
|
||||
|
||||
// Create new FormData for upstream request
|
||||
const upstreamFormData = new FormData();
|
||||
|
||||
// Copy all fields
|
||||
for (const [key, value] of incomingFormData.entries()) {
|
||||
if (value instanceof File) {
|
||||
// For files, we need to create a new Blob
|
||||
const arrayBuffer = await value.arrayBuffer();
|
||||
const blob = new Blob([arrayBuffer], { type: value.type });
|
||||
upstreamFormData.append(key, blob, value.name);
|
||||
} else {
|
||||
upstreamFormData.append(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[upload] Proxying to:', `${CITY_SERVICE_URL}/city/assets/upload`);
|
||||
console.log('[upload] Fields:', [...incomingFormData.keys()]);
|
||||
|
||||
const upstream = await fetch(`${CITY_SERVICE_URL}/city/assets/upload`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
body: upstreamFormData,
|
||||
});
|
||||
|
||||
const responseText = await upstream.text();
|
||||
console.log('[upload] Response status:', upstream.status);
|
||||
console.log('[upload] Response body:', responseText.substring(0, 500));
|
||||
|
||||
if (!upstream.ok) {
|
||||
const errorText = await upstream.text();
|
||||
return NextResponse.json(
|
||||
{ error: 'Upload failed', details: errorText },
|
||||
{ error: 'Upload failed', details: responseText },
|
||||
{ status: upstream.status }
|
||||
);
|
||||
}
|
||||
|
||||
const data = await upstream.json();
|
||||
return NextResponse.json(data, { status: 200 });
|
||||
try {
|
||||
const data = JSON.parse(responseText);
|
||||
return NextResponse.json(data, { status: 200 });
|
||||
} catch {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid response from server', details: responseText },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[upload] Error:', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Upload failed',
|
||||
|
||||
@@ -5,6 +5,15 @@ const CITY_SERVICE_URL =
|
||||
process.env.CITY_SERVICE_URL ||
|
||||
'http://daarion-city-service:7001';
|
||||
|
||||
// Fallback response when swapper data is unavailable
|
||||
const fallbackResponse = (nodeId: string) => ({
|
||||
node_id: nodeId,
|
||||
healthy: false,
|
||||
models_loaded: 0,
|
||||
models_total: 0,
|
||||
models: [],
|
||||
});
|
||||
|
||||
export async function GET(
|
||||
_request: NextRequest,
|
||||
{ params }: { params: Promise<{ nodeId: string }> }
|
||||
@@ -19,26 +28,30 @@ export async function GET(
|
||||
}
|
||||
|
||||
try {
|
||||
const upstream = await fetch(
|
||||
`${CITY_SERVICE_URL}/city/internal/node/${encodeURIComponent(nodeId)}/swapper`,
|
||||
{
|
||||
cache: 'no-store',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
const url = `${CITY_SERVICE_URL}/city/internal/node/${encodeURIComponent(nodeId)}/swapper`;
|
||||
console.log('[swapper] Fetching:', url);
|
||||
|
||||
const upstream = await fetch(url, {
|
||||
cache: 'no-store',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
console.log('[swapper] Response status:', upstream.status);
|
||||
|
||||
if (!upstream.ok) {
|
||||
// Return fallback instead of error
|
||||
console.log('[swapper] Upstream not ok, returning fallback');
|
||||
return NextResponse.json(fallbackResponse(nodeId), { status: 200 });
|
||||
}
|
||||
|
||||
const payload = await upstream.json();
|
||||
return NextResponse.json(payload, { status: upstream.status });
|
||||
return NextResponse.json(payload, { status: 200 });
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Failed to fetch swapper data',
|
||||
details: error instanceof Error ? error.message : String(error),
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
// Return fallback instead of error
|
||||
console.error('[swapper] Error:', error);
|
||||
return NextResponse.json(fallbackResponse(nodeId), { status: 200 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,20 +27,8 @@ export function NodeSwapperCard({ nodeId }: NodeSwapperCardProps) {
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="bg-red-500/10 backdrop-blur-md rounded-2xl border border-red-500/20 p-6">
|
||||
<h3 className="text-red-400 font-medium mb-2">Swapper Service Unavailable</h3>
|
||||
<p className="text-white/50 text-sm">Failed to load swapper details.</p>
|
||||
<button
|
||||
onClick={() => mutate()}
|
||||
className="mt-4 text-xs text-white/40 hover:text-white hover:underline"
|
||||
>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// Don't show error state - fallback to pending data view instead
|
||||
// The API now always returns 200 with fallback data
|
||||
|
||||
return (
|
||||
<div className="bg-white/5 backdrop-blur-md rounded-2xl border border-white/10 p-6">
|
||||
|
||||
Reference in New Issue
Block a user