Image URL Validation
Client-Side Validation for Image URLs (Not Recommended)
Using client-side validation for image URLs can lead to CORS errors and may not work for all valid image URLs (even if its valid one). The following example demonstrates this approach:
link: z
.string()
.url("Invalid Image URL")
.refine(async (url) => {
try {
const res = await fetch(url, { method: "HEAD" });
const contentType = res.headers.get("content-type");
return contentType?.startsWith("image/");
} catch {
return false;
}
}, "URL must be a valid image"),
Server-Side Validation (Recommended)
Instead, it's recommended to perform server-side validation using an API route. Here's how you can implement it:
- Use server-side validation for image URLs using server actions in the form component itself or if you want to do it formSchema with zod you can do something like:
1. You can implement it using an API route. Here's how you can implement it:
link: z.string()
.url("Invalid Image URL")
.refine(async (url) => {
try {
const res = await fetch(
`/api/validateImage?url=${encodeURIComponent(url)}`
);
const data = await res.json();
return data.valid;
} catch {
return false;
}
}, "URL must be a valid image");
create an API route at /api/validateImage and it will return either true or false depending on whether the image URL is valid or not.
app/api/validateImage/route.ts
import { NextResponse } from "next/server";
export async function GET(request: Request) {
// new URL(request.url): This creates a new URL object from the incoming request’s URL. It parses the string and provides access to various parts of the URL.
const { searchParams } = new URL(request.url); //Destructuring searchParams:
// we can destructure searchParams directly from the URL object. This allows you to access the query parameters without needing to reference the URL object again.
const url = searchParams.get("url"); // This method retrieves the value of the url parameter from the query string. If the URL is /api/validateImage?url=https://example.com/image.jpg, searchParams.get("url") will return https://example.com/image.jpg. If the parameter doesn’t exist, it returns null.
// Validating the URL
if (!url) {
return NextResponse.json(
{ valid: false, error: "Invalid URL provided" },
{ status: 400 }
);
}
try {
const response = await fetch(url, { method: "HEAD" });
const contentType = response.headers.get("content-type");
if (response.ok && contentType?.startsWith("image/")) {
return NextResponse.json({ valid: true });
} else {
return NextResponse.json(
{ valid: false, error: "URL is not a valid image" },
{ status: 400 }
);
}
} catch {
return NextResponse.json(
{ valid: false, error: "Unable to fetch URL" },
{ status: 500 }
);
}
}
2. Recommmend doing a server side validation for img URL using server actions.
actions.ts
"use server";
export async function validateImageURL(url: string): Promise<boolean> {
try {
const response = await fetch(url, { method: "HEAD" });
const contentType = response.headers.get("content-type");
console.log(contentType);
return contentType?.startsWith("image/") ?? false;
} catch (error) {
console.error("Error validating image URL:", error);
return false;
}
}
- Use the
validateImageURLserver action in your form component itself (makes it easier to maintain but more complex and verbose).
const isImageValid = await validateImageURL(formValues.link);
if (!isImageValid) {
setErrors((prevErrors) => ({
link: "Invalid image URL",
}));
toast({
title: "Error",
description: "The provided image URL is not valid",
variant: "destructive",
className: "bg-red-500 text-white border border-red-700",
});
// Return early with an error status
return {
...prevState,
error: "Invalid image URL",
status: "ERROR",
values: formValues,
};
}
- You can also use the
validateImageURLserver action in your formSchema with zod (refine method), you can do something like.
link: z
.string()
.url("Invalid Image URL")
.refine(async (url) => await validateImageURL(url), {
message: "URL must be a valid image",
}),
- Although it works, I dont know if it is a recommended practice to do server side validation in zod schema or not.
- If face any issues you can call server-actions in your form component itself.