I have a Vite/Vue 3 application where I get an error like this when loading images.
Access to image at 'https://website.com/image-url.jpg' from origin 'https://my-web-app-url.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
The function that loads images looks like this:
const imageLoader = (image: HTMLImageElement, url: string): Promise<HTMLImageElement> => {
return new Promise((resolve, reject) => {
image.crossOrigin = "Anonymous";
image.src = url;
image.onload = () => resolve(image);
image.onerror = () => reject(image);
});
};
I need to load an image in order to create a canvas with the loaded image, this function looks like this:
const createCanvas = async (url: string): Promise<CanvasObject | null> => {
const image = new Image();
const loaded = await imageLoader(image, url);
const canvas = document.createElement("canvas");
canvas.setAttribute("visibility", "hidden");
canvas.width = loaded.width;
canvas.height = loaded.height;
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.drawImage(image, 0, 0);
return { ctx, width: image.width, height: image.height };
} else {
console.error("context not found");
return null;
}
};
What i've already try:
image.crossOrigin = "Anonymous"
image.src = url + "?" + new Date().getTime()
server: { cors: { origin: "*" }, }
server: { proxy: { "/": { target: "https://image-aware-background.vercel.app", changeOrigin: true, secure: false, rewrite: (path) => path.replace(/^\//, ""), }, }, }
But none of these methods helped me to solve the CORS error.
I see the access-control-allow-origin header in the original application request, but it is not in the image download request.
How to reproduce issue:
Okay, I was able to figure it out after all, thanks to Ali Bahrami.
If you need to download an image from a server that has a strictly configured CORS, you need to use a proxy server, which will return the data to you with the required headers.
I used https://allorigins.win/. You need to put the address of the proxy server at the beginning of your url.
https://api.allorigins.win/raw?url=https://example.org/
So, my image loader function started looking like this:
export const imageLoader = (image: HTMLImageElement, url: string): Promise<HTMLImageElement> => {
return new Promise((resolve, reject) => {
image.crossOrigin = "Anonymous";
image.src = "https://api.allorigins.win/raw?url=" + url;
image.onload = () => resolve(image);
image.onerror = () => reject(image);
});
};