80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
|
|
/**
|
|
* Image proxy route to serve Strapi images over HTTPS
|
|
* This solves the Mixed Content issue when Strapi only serves HTTP
|
|
*/
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
const searchParams = request.nextUrl.searchParams
|
|
const imageUrl = searchParams.get('url')
|
|
|
|
if (!imageUrl) {
|
|
return NextResponse.json({ error: 'Missing url parameter' }, { status: 400 })
|
|
}
|
|
|
|
// Decode the URL
|
|
const decodedUrl = decodeURIComponent(imageUrl)
|
|
|
|
// Get base URL from environment
|
|
const strapiBaseUrl = process.env.NEXT_PUBLIC_STRAPI_BASE_URL || "http://160.187.167.213"
|
|
const baseUrl = strapiBaseUrl.replace(/\/+$/, "")
|
|
|
|
// Construct the full image URL (always use HTTP for Strapi server-side)
|
|
let fullImageUrl: string
|
|
if (decodedUrl.startsWith("http://") || decodedUrl.startsWith("https://")) {
|
|
// If it's already absolute, convert HTTPS to HTTP for Strapi
|
|
// Also extract just the path if it's from the Strapi domain
|
|
const urlObj = new URL(decodedUrl)
|
|
if (urlObj.hostname === "160.187.167.213" || urlObj.hostname.includes("160.187.167.213")) {
|
|
// It's from Strapi, use HTTP
|
|
fullImageUrl = `http://${urlObj.hostname}${urlObj.pathname}${urlObj.search}`
|
|
} else {
|
|
// Different domain, keep original but convert HTTPS to HTTP
|
|
fullImageUrl = decodedUrl.replace(/^https:\/\//, "http://")
|
|
}
|
|
} else {
|
|
// Relative URL - construct with base URL
|
|
const normalizedUrl = decodedUrl.startsWith("/") ? decodedUrl : `/${decodedUrl}`
|
|
fullImageUrl = `${baseUrl}${normalizedUrl}`
|
|
}
|
|
|
|
// Fetch the image from Strapi (server-side, so HTTP is fine)
|
|
const imageResponse = await fetch(fullImageUrl, {
|
|
headers: {
|
|
'User-Agent': 'Mozilla/5.0',
|
|
},
|
|
next: { revalidate: 3600 }, // Cache for 1 hour
|
|
})
|
|
|
|
if (!imageResponse.ok) {
|
|
console.error(`Failed to fetch image from Strapi: ${fullImageUrl}`, imageResponse.status)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to fetch image' },
|
|
{ status: imageResponse.status }
|
|
)
|
|
}
|
|
|
|
// Get the image data
|
|
const imageBuffer = await imageResponse.arrayBuffer()
|
|
const contentType = imageResponse.headers.get('content-type') || 'image/png'
|
|
|
|
// Return the image with proper headers
|
|
return new NextResponse(imageBuffer, {
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': contentType,
|
|
'Cache-Control': 'public, max-age=3600, s-maxage=3600, stale-while-revalidate=86400',
|
|
'Access-Control-Allow-Origin': '*',
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error('Error proxying image:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Internal server error' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|