Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/apps/posterize/pages/PosterizePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from 'react'
import styles from './PosterizePage.module.css'
import PosterizeNavigation from '../components/PosterizeNavigation'
import ImageUploader from '../components/ImageUploader'
import { handleApiResponse } from '@/utils/apiUtils'

interface BlurResponse {
width: number
Expand Down Expand Up @@ -55,12 +56,7 @@ const PosterizePage = () => {
}),
})

if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.error || `HTTP error! status: ${response.status}`)
}

const data: BlurResponse = await response.json()
const data: BlurResponse = await handleApiResponse<BlurResponse>(response)
setBlurredImage(data)

// Auto-scroll to result after successful blur on mobile
Expand Down
28 changes: 17 additions & 11 deletions src/apps/tracy/pages/TracyPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from 'react'
import styles from './TracyPage.module.css'
import TracySceneEditor from '../components/TracySceneEditor'
import TracyNavigation from '../components/TracyNavigation'
import { handleApiResponse } from '@/utils/apiUtils'

interface SceneData {
scene: {
Expand Down Expand Up @@ -30,6 +31,20 @@ interface SceneData {
}
}

interface TracyResponse {
base64_png: string
width: number
height: number
}

interface BlurResponse {
image_data: string
width: number
height: number
format: string
size_bytes: number
}

const TracyPage = () => {
const [imageData, setImageData] = useState<{ base64_png: string; width: number; height: number } | null>(null)
const [isLoading, setIsLoading] = useState(false)
Expand Down Expand Up @@ -59,11 +74,7 @@ const TracyPage = () => {
body: JSON.stringify(sceneData),
})

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}

const data = await response.json()
const data = await handleApiResponse<TracyResponse>(response)
setImageData(data)

// Auto-scroll to result after successful render on mobile
Expand Down Expand Up @@ -145,12 +156,7 @@ const TracyPage = () => {
}),
})

if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.error || `HTTP error! status: ${response.status}`)
}

const blurredData = await response.json()
const blurredData = await handleApiResponse<BlurResponse>(response)

// Replace the current image with the blurred version
setImageData({
Expand Down
38 changes: 38 additions & 0 deletions src/utils/apiUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Handles API response parsing with better error handling for non-JSON responses
* Common in cases where request bodies exceed size limits and proxies return text
*/
export async function handleApiResponse<T>(response: Response): Promise<T> {
if (!response.ok) {
let errorMessage = `HTTP error! status: ${response.status}`

try {
const errorData = await response.json()
errorMessage = errorData.error || errorMessage
} catch {
// If JSON parsing fails, try to get text response
try {
const errorText = await response.text()
// Check if it looks like a size/length error
if (errorText.toLowerCase().includes('too large') ||
errorText.toLowerCase().includes('size') ||
errorText.toLowerCase().includes('limit') ||
response.status === 413) {
errorMessage = 'The image is too large. Please choose a smaller image or reduce its quality.'
} else if (errorText && errorText.length < 200) {
// Use the text if it's reasonably short
errorMessage = errorText
}
} catch {
// If both JSON and text parsing fail, use a user-friendly message
if (response.status === 413) {
errorMessage = 'The image is too large. Please choose a smaller image or reduce its quality.'
}
}
}

throw new Error(errorMessage)
}

return response.json()
}