apix/app/api/generate/route.ts
Khoa.vo 2a8125f6d7
Some checks are pending
CI / build (18.x) (push) Waiting to run
CI / build (20.x) (push) Waiting to run
fix: Cookie parsing for JSON format in upload and generate APIs
- Fixed upload route to properly trim and parse JSON-formatted cookies
- Added same cookie normalization logic to generate route
- Handles pretty-printed JSON with leading newlines from Cookie-Editor export
2026-01-05 15:01:24 +07:00

71 lines
3 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { WhiskClient } from '@/lib/whisk-client';
import { cookies } from 'next/headers';
export async function POST(req: NextRequest) {
try {
const { prompt, aspectRatio, refs, preciseMode, imageCount = 1, cookies: clientCookies } = await req.json();
if (!prompt) {
return NextResponse.json({ error: "Prompt is required" }, { status: 400 });
}
// Use cookies provided in request or fallback to server-side logic if implemented later
// For now, we expect the frontend to pass the 'whisk_cookies' it has stored.
let cookieString = clientCookies || req.cookies.get('whisk_cookies')?.value;
if (!cookieString) {
return NextResponse.json({ error: "Whisk cookies not found. Please configure settings." }, { status: 401 });
}
// Normalize cookies: handle JSON-formatted cookies (from Cookie-Editor export)
const trimmedCookies = cookieString.trim();
if (trimmedCookies.startsWith('[') || trimmedCookies.startsWith('{')) {
try {
const cookieArray = JSON.parse(trimmedCookies);
if (Array.isArray(cookieArray)) {
cookieString = cookieArray
.map((c: any) => `${c.name}=${c.value}`)
.join('; ');
console.log(`[Generate] Parsed ${cookieArray.length} cookies from JSON.`);
}
} catch (e) {
console.warn("[Generate] Failed to parse cookie JSON:", e);
}
}
const client = new WhiskClient(cookieString);
// Generate images in parallel if imageCount > 1
// Whisk API typically returns 1-4 images per call, but we treat each call as a request set
// If imageCount is requested, we make that many parallel requests to ensure sufficient output
// (Note: To be safer with rate limits, we cap parallelism at 4)
const parallelCount = Math.min(Math.max(1, imageCount), 4);
console.log(`Starting ${parallelCount} parallel generation requests for prompt: "${prompt.substring(0, 20)}..."`);
const promises = Array(parallelCount).fill(null).map(() =>
client.generate(prompt, aspectRatio, refs, preciseMode)
.catch(err => {
console.error("Single generation request failed:", err);
return []; // Return empty array on failure to let others proceed
})
);
const results = await Promise.all(promises);
const images = results.flat();
if (images.length === 0) {
throw new Error("All generation requests failed. Check logs or try again.");
}
return NextResponse.json({ images });
} catch (error: any) {
console.error("Generate API Error:", error);
return NextResponse.json(
{ error: error.message || "Generation failed" },
{ status: 500 }
);
}
}