NextJS not working well

#4
by dingdong1009 - opened

Hi - i'd like to see if you can support.

i'm deploying your model solution to nextJS app.
and I cannot seem to make it work somehome.
it generates the pictures, but completely changed the model, and background. can you help?
i'm providing attached the screenshot of the output result and the code associated. would be nice if you could help.

this is my route.ts file

import { NextRequest, NextResponse } from 'next/server'
import crypto from 'crypto'

// Environment variables based on official Python implementation
const BASE_URL = process.env.WESHOP_BASE_URL || 'https://openapi.weshop.ai'
const UPLOAD_IMAGE_URL = process.env.WESHOP_UPLOAD_IMAGE_URL || '/openapi/v1/asset/upload/image'
const UPLOAD_BACKGROUND_IMAGE_URL = process.env.WESHOP_UPLOAD_BACKGROUND_IMAGE_URL || '/openapi/v1/asset/upload/background_image'
const CREATE_SAVE_TASK_URL = process.env.WESHOP_CREATE_SAVE_TASK_URL || '/openapi/v1/agent/task/create'
const EXECUTE_TASK_URL = process.env.WESHOP_EXECUTE_TASK_URL || '/openapi/v1/agent/task/execute'
const QUERY_TASK_URL = process.env.WESHOP_QUERY_TASK_URL || '/openapi/v1/agent/task/query'

// Support both authentication methods
const SECRET_KEY = process.env.WESHOP_SECRET_KEY
const APP_ID = process.env.WESHOP_APP_ID
const API_KEY = process.env.WESHOP_API_KEY // Fallback to simple API key
const AGENT_VERSION = process.env.WESHOP_AGENT_VERSION || 'v1.0'
const AGENT_NAME = process.env.WESHOP_AGENT_NAME || 'aimodel'

// Check if we have either HMAC auth or simple API key
if (!SECRET_KEY && !API_KEY) {
console.error('WeShop authentication not configured: Need either WESHOP_SECRET_KEY+WESHOP_APP_ID or WESHOP_API_KEY')
}

const USE_HMAC_AUTH = !!(SECRET_KEY && APP_ID)
console.log('๐Ÿ” Using authentication method:', USE_HMAC_AUTH ? 'HMAC Signature' : 'API Key')

interface WeShopResponse {
success?: boolean
code?: string | number
msg?: string
message?: string
data?: any
}

function parseResponse(response: Response, data: WeShopResponse): { data: any; msg: string } {
let msg = ''
let responseData = null

console.log('๐Ÿ“Š Response status:', response.status, response.statusText)
console.log('๐Ÿ“‹ Response data:', JSON.stringify(data, null, 2))

if (response.status === 200) {
if (data) {
responseData = data.data
if (!responseData) {
msg = data.msg || data.message || "Field error."
}
} else {
msg = "The parsing result is empty."
}
} else {
msg = Request error: ${response.status} ${response.statusText}. Response: ${JSON.stringify(data)}
}

return { data: responseData, msg }
}

function generateSignature(key: string, did: string, timestamp: string): string {
const data = ${did}:${timestamp}
const hmac = crypto.createHmac('sha256', key)
hmac.update(data)
return hmac.digest('hex')
}

function generateDid(): string {
return crypto.randomUUID()
}

function getHeaders(did: string, clientIp: string, userId?: string, userName?: string) {
if (USE_HMAC_AUTH) {
// HMAC Signature Authentication (official method)
const timestamp = Math.floor(Date.now() / 1000).toString()
const signature = generateSignature(SECRET_KEY!, did, timestamp)

return {
  'Did': did,
  'X-Timestamp': timestamp,
  'X-Signature': signature,
  'X-Forwarded-For': clientIp,
  'X-AppId': APP_ID!,
  'X-HfUid': userId || '',
  'X-HfUserName': userName || '',
}

} else {
// Simple API Key Authentication (fallback)
return {
'Authorization': API_KEY!,
'X-Forwarded-For': clientIp,
}
}
}

async function uploadImage(
imageFile: File,
uploadType: 'image' | 'background_image',
did: string,
clientIp: string,
userId?: string,
userName?: string
): Promise<{ data: any; msg: string }> {
const uploadUrl = uploadType === 'image' ? UPLOAD_IMAGE_URL : UPLOAD_BACKGROUND_IMAGE_URL

console.log(๐Ÿ“ค Uploading ${uploadType}:, imageFile.name, 'Size:', Math.round(imageFile.size / 1024) + 'KB')

// File validation
if (imageFile.size > 10 * 1024 * 1024) {
throw new Error('Image file too large. Please use an image smaller than 10MB.')
}

if (!imageFile.type.startsWith('image/')) {
throw new Error('Invalid file type. Please upload an image file.')
}

const formData = new FormData()
formData.append('image', imageFile)

const headers = getHeaders(did, clientIp, userId, userName)

try {
console.log('๐ŸŒ Making request to:', ${BASE_URL}${uploadUrl})
console.log('๐Ÿ“‹ Request headers:', JSON.stringify(headers, null, 2))

const response = await fetch(`${BASE_URL}${uploadUrl}`, {
  method: 'POST',
  headers,
  body: formData
})

console.log('๐Ÿ“Š Upload response status:', response.status, response.statusText)

let data: WeShopResponse
try {
  data = await response.json()
} catch (parseError) {
  const responseText = await response.text()
  console.error('โŒ Failed to parse JSON response:', responseText)
  throw new Error(`Invalid JSON response: ${responseText}`)
}

return parseResponse(response, data)

} catch (error) {
console.error('โŒ Upload error:', error)
if (error instanceof TypeError && error.message.includes('fetch')) {
throw new Error(Network error: Unable to connect to WeShop API at ${BASE_URL}${uploadUrl})
}
throw error
}
}

async function createTask(
imageUrl: string,
did: string,
clientIp: string,
userId?: string,
userName?: string
): Promise<{ data: any; msg: string }> {
console.log('๐Ÿ”ง Creating task with garment image:', imageUrl)

const headers = {
...getHeaders(did, clientIp, userId, userName),
'Content-Type': 'application/json',
}

const requestData = {
agentVersion: AGENT_VERSION,
agentName: AGENT_NAME,
image: imageUrl
}

console.log('๐Ÿ“‹ Create task request:', JSON.stringify(requestData, null, 2))

try {
console.log('๐ŸŒ Making request to:', ${BASE_URL}${CREATE_SAVE_TASK_URL})
console.log('๐Ÿ“‹ Request headers:', JSON.stringify(headers, null, 2))

const response = await fetch(`${BASE_URL}${CREATE_SAVE_TASK_URL}`, {
  method: 'POST',
  headers,
  body: JSON.stringify(requestData)
})

let data: WeShopResponse
try {
  data = await response.json()
} catch (parseError) {
  const responseText = await response.text()
  console.error('โŒ Failed to parse JSON response:', responseText)
  throw new Error(`Invalid JSON response: ${responseText}`)
}

return parseResponse(response, data)

} catch (error) {
console.error('โŒ Create task error:', error)
if (error instanceof TypeError && error.message.includes('fetch')) {
throw new Error(Network error: Unable to connect to WeShop API at ${BASE_URL}${CREATE_SAVE_TASK_URL})
}
throw error
}
}

async function saveTask(
imageUrl: string,
showImage: string,
taskId: string,
locationData: any,
did: string,
clientIp: string,
userId?: string,
userName?: string
): Promise<{ data: any; msg: string }> {
console.log('๐Ÿ’พ Saving task with person image')

const headers = {
...getHeaders(did, clientIp, userId, userName),
'Content-Type': 'application/json',
}

const requestData = {
agentVersion: AGENT_VERSION,
agentName: AGENT_NAME,
image: imageUrl,
showImage: showImage,
taskId: taskId,
locationId: locationData,
}

console.log('๐Ÿ“‹ Save task request:', JSON.stringify(requestData, null, 2))

try {
const response = await fetch(${BASE_URL}${CREATE_SAVE_TASK_URL}, {
method: 'POST',
headers,
body: JSON.stringify(requestData)
})

const data: WeShopResponse = await response.json()
console.log('๐Ÿ“‹ Save task response:', JSON.stringify(data, null, 2))

return parseResponse(response, data)

} catch (error) {
console.error('โŒ Save task error:', error)
throw error
}
}

async function startTask(
taskId: string,
did: string,
clientIp: string,
userId?: string,
userName?: string
): Promise<{ data: any; msg: string }> {
console.log('โšก Starting task execution:', taskId)

const headers = {
...getHeaders(did, clientIp, userId, userName),
'Content-Type': 'application/json',
}

const requestData = {
agentVersion: AGENT_VERSION,
agentName: AGENT_NAME,
taskId: taskId,
runFreeAsFallback: false
}

console.log('๐Ÿ“‹ Start task request:', JSON.stringify(requestData, null, 2))

try {
const response = await fetch(${BASE_URL}${EXECUTE_TASK_URL}, {
method: 'POST',
headers,
body: JSON.stringify(requestData)
})

const data: WeShopResponse = await response.json()
console.log('๐Ÿ“‹ Start task response:', JSON.stringify(data, null, 2))

return parseResponse(response, data)

} catch (error) {
console.error('โŒ Start task error:', error)
throw error
}
}

async function queryTask(
taskId: string,
executionId: string,
did: string,
clientIp: string,
userId?: string,
userName?: string
): Promise<{ data: any; msg: string }> {
const headers = {
...getHeaders(did, clientIp, userId, userName),
'Content-Type': 'application/json',
}

const requestData = {
agentVersion: AGENT_VERSION,
agentName: AGENT_NAME,
taskId: taskId,
executionId: executionId,
}

try {
const response = await fetch(${BASE_URL}${QUERY_TASK_URL}, {
method: 'POST',
headers,
body: JSON.stringify(requestData)
})

const data: WeShopResponse = await response.json()
console.log('๐Ÿ“‹ Query task response:', JSON.stringify(data, null, 2))

return parseResponse(response, data)

} catch (error) {
console.error('โŒ Query task error:', error)
throw error
}
}

async function pollTaskCompletion(
taskId: string,
executionId: string,
did: string,
clientIp: string,
userId?: string,
userName?: string,
maxAttempts = 1800 // 1 hour with 2-second intervals
): Promise<string[]> {
const startTime = Date.now()

for (let attempt = 0; attempt < maxAttempts; attempt++) {
const { data: queryData, msg } = await queryTask(taskId, executionId, did, clientIp, userId, userName)

if (!queryData) {
  console.warn('โŒ Query failed:', msg)
  await new Promise(resolve => setTimeout(resolve, 2000))
  continue
}

const executions = queryData.executions
if (!executions || !executions.length) {
  await new Promise(resolve => setTimeout(resolve, 2000))
  continue
}

const results = executions[0].result
if (!results || !results.length) {
  await new Promise(resolve => setTimeout(resolve, 2000))
  continue
}

const status = results[0].status
console.log(`๐Ÿ“Š Poll attempt ${attempt + 1}: Status = ${status}`)

if (status === 'Failed') {
  throw new Error('The person image does not match your garment. It is recommended to change to a different one.')
}

if (status === 'Success' || status === 'Blocked') {
  const image = results[0].image
  if (image && image.trim() !== '') {
    console.log('โœ… Task completed successfully')
    return [image] // Return as array for consistency
  }
}

// Check timeout (1 hour)
const elapsedTime = Date.now() - startTime
if (elapsedTime > 3600000) {
  throw new Error('Query task timeout.')
}

await new Promise(resolve => setTimeout(resolve, 2000))

}

throw new Error('Task timed out - maximum polling attempts reached')
}

export async function POST(request: NextRequest) {
try {
if (!SECRET_KEY && !API_KEY) {
return NextResponse.json(
{ error: 'WeShop authentication not configured. Set WESHOP_API_KEY or WESHOP_SECRET_KEY+WESHOP_APP_ID' },
{ status: 500 }
)
}

if (USE_HMAC_AUTH && (!SECRET_KEY || !APP_ID)) {
  return NextResponse.json(
    { error: 'HMAC authentication requires both WESHOP_SECRET_KEY and WESHOP_APP_ID' },
    { status: 500 }
  )
}

console.log('๐Ÿš€ Starting WeShop AI try-on process...')

// Get client IP
const clientIp = request.headers.get('x-forwarded-for') || 
                request.headers.get('x-real-ip') || 
                '127.0.0.1'

// Generate unique device ID
const did = generateDid()
console.log('๐Ÿ”‘ Generated DID:', did)
console.log('๐ŸŒ Client IP:', clientIp)

const formData = await request.formData()
const personImage = formData.get('personImage') as File // This will be background/person
const clothingImage = formData.get('clothingImage') as File // This will be main/garment

if (!personImage || !clothingImage) {
  return NextResponse.json(
    { error: 'Both person and clothing images are required' },
    { status: 400 }
  )
}

// Step 1: Upload garment image (main image)
console.log('๐Ÿ“ค Step 1: Uploading garment image...')
const { data: garmentUploadData, msg: garmentUploadMsg } = await uploadImage(
  clothingImage, 'image', did, clientIp
)

if (!garmentUploadData) {
  throw new Error(garmentUploadMsg || 'Failed to upload garment image')
}

const garmentImageUrl = garmentUploadData.image
if (!garmentImageUrl) {
  throw new Error('Upload garment image failed - no image URL returned')
}

console.log('โœ… Garment image uploaded:', garmentImageUrl)

// Step 2: Create task with garment image
console.log('๐Ÿ”ง Step 2: Creating task with garment image...')
const { data: createTaskData, msg: createTaskMsg } = await createTask(
  garmentImageUrl, did, clientIp
)

if (!createTaskData) {
  throw new Error(createTaskMsg || 'Failed to create task')
}

const taskId = createTaskData.taskId
const showImage = createTaskData.showImage

if (!taskId || !showImage) {
  throw new Error('Create task failed - missing taskId or showImage')
}

console.log('โœ… Task created:', taskId)

// Step 3: Upload person image (background image)
console.log('๐Ÿ“ค Step 3: Uploading person image...')
const { data: personUploadData, msg: personUploadMsg } = await uploadImage(
  personImage, 'background_image', did, clientIp
)

if (!personUploadData) {
  throw new Error(personUploadMsg || 'Failed to upload person image')
}

console.log('โœ… Person image uploaded')

// Step 4: Save task with person image and location
console.log('๐Ÿ’พ Step 4: Saving task with person image...')
const { data: saveTaskData, msg: saveTaskMsg } = await saveTask(
  garmentImageUrl, showImage, taskId, personUploadData, did, clientIp
)

if (!saveTaskData) {
  throw new Error(saveTaskMsg || 'Failed to save task')
}

const saveTaskId = saveTaskData.taskId
const saveShowImage = saveTaskData.showImage

if (!saveTaskId || !saveShowImage) {
  throw new Error('Save task failed - missing taskId or showImage')
}

console.log('โœ… Task saved')

// Step 5: Start task execution
console.log('โšก Step 5: Starting task execution...')
const { data: startTaskData, msg: startTaskMsg } = await startTask(
  saveTaskId, did, clientIp
)

if (!startTaskData) {
  throw new Error(startTaskMsg || 'Failed to start task')
}

const executionId = startTaskData.executionId
if (!executionId) {
  throw new Error('The task failed to start - no execution ID')
}

console.log('โœ… Task execution started:', executionId)

// Step 6: Poll for completion
console.log('โณ Step 6: Polling for completion...')
const resultImages = await pollTaskCompletion(
  saveTaskId, executionId, did, clientIp
)

console.log('๐ŸŽ‰ Task completed successfully!')

return NextResponse.json({
  success: true,
  resultImage: resultImages[0],
  allResults: resultImages,
  taskId: saveTaskId,
  executionId,
  debug: {
    did,
    garmentImageUrl,
    personUploadData,
    clientIp,
    resultsCount: resultImages.length
  }
})

} catch (error) {
console.error('โŒ WeShop AI try-on error:', error)

return NextResponse.json(
  { 
    error: error instanceof Error ? error.message : 'Unknown error occurred',
    details: process.env.NODE_ENV === 'development' ? String(error) : undefined
  },
  { status: 500 }
)

}
}

Screenshot 2025-06-21 at 15.22.43.png

thanks for your help!

Sign up or log in to comment