Bypass CORS with Next.js 13’s App Dir API and a Proxied Image Component
Dealing with CORS can be tricky, especially when fetching resources from different domains. Here's how you can use Next.js to navigate around it efficiently.
1. Setting Up the Proxy Route
First, let's set up a server-side API route in Next.js to serve as a proxy for our requests.
Create a new folder named
proxy
in yourapp/api
directory.Add a file named
route.ts
and add the following:
import { NextRequest, NextResponse } from "next/server";
import axios from "axios";
const DEFAULT_CONTENT_TYPE = "image/jpeg";
const MISSING_URL_ERROR = {
message: "URL parameter is missing.",
status: 400
};
const GENERIC_FETCH_ERROR = {
message: "Failed to fetch resource.",
status: 500
};
const HEADERS = {
"Access-Control-Allow-Origin": "*",
};
export async function GET(request: NextRequest) {
const url = request.nextUrl.searchParams.get("url");
if (!url) {
return NextResponse.json(MISSING_URL_ERROR.message, { status: MISSING_URL_ERROR.status });
}
try {
const response = await axios.get(url, { responseType: "arraybuffer" });
const contentType = response.headers["content-type"] || DEFAULT_CONTENT_TYPE;
return new NextResponse(response.data, {
headers: {
...HEADERS,
"Content-Type": contentType,
},
});
} catch (error) {
const status = error.response?.status || GENERIC_FETCH_ERROR.status;
return NextResponse.json(
{ error: `${GENERIC_FETCH_ERROR.message} Status: ${status}` },
{ status }
);
}
}
Think of the proxy route as a discreet middleman that retrieves data for you, without getting tangled in CORS.
2. Using the Proxied Image Component
With the backend ready, let's build a frontend component to use our proxy effectively with Next’s Image component:
Create a new file
ProxiedImage.tsx
in your components directory.Implement the following code:
import Image from "next/image";
const getProxiedImageUrl = (originalUrl) => {
return `/api/proxy?url=${encodeURIComponent(originalUrl)}`;
};
const ProxiedImage = ({ src, width, height, alt = "Image", ...restProps }) => {
const proxiedImage = getProxiedImageUrl(src);
return (
<Image
{...restProps}
src={proxiedImage}
alt={alt}
width={width}
height={height}
loading="lazy"
crossOrigin="anonymous"
/>
);
};
export default ProxiedImage;
3. Putting It All Together
To fetch an image from a different origin, simply use the ProxiedImage
component:
<ProxiedImage src="https://external-site.com/image.jpg" width={500} height={500} />
With this setup, the request will go to our proxy endpoint first, and then the proxy will fetch the image from the external site. Since the proxy is on the same origin as our app, we bypass CORS restrictions.
Conclusion
Tackling CORS can seem daunting, but with Next.js, it's just another hurdle. This proxy and image component combo not only simplifies cross-origin challenges but also streamlines your workflow. Keep building, stay innovative, and let Next.js do the heavy lifting! 🚀