A CORS Go-To-Bed Tale
I create apps for a living. Specifically, apps that run on a Set-Top Box –an embedded system with less RAM than a Raspberry Pi– rendering on a TV. ..to put it formally: I create React apps that runs on an ancient browser on top of a '90s' embedded system with lower specs than a Raspberry Pi, displayed on your TV. yes, it's a challenge. Right now we're building an 'Amazon'-like app: a grid of products. Using the TV remote you can move through the grid of products. You get the idea. Lately we've been playing with WebGL graphics. Using .path() .fill() on a is more perfomant than translating regular s! We use pixi.js: a –quote– "rendering system that uses WebGL (or optionally Canvas) to display images and other 2D visual content". Hold on i'm getting there To load the images, you need first to load on an Asset's cache like: import { Assets } from 'pixi.js'; await Assets.load({ src: image.url, alias: image.url, loadParser: 'loadTextures', }); Which is –checked in their GitHub– doing a regular GET using fetch(). ... And that, led to CORS error cause Assets.load({ src }) is trying to fetch the resource from a server from a third party. And i have no control over this server. CORS strikes back CORS –yes there are millions of posts explaining CORS– CORS is expected. Browsers, before making any request, send a pre-flight request (an HTTP OPTIONS) asking the server: "ey buddy, I’d like to request this resource from you, and I’m from this origin, which is different from yours. is ok?" If the server doesn’t explicitly allow the request from this "outsider" (i.e., by returning an Access-Control-Allow-Origin header with the origin it agrees to), the browser itself blocks the request. So, as an app, when I try to request something from a server, the browser ensures that the deal is consented. How to solve CORS The "ey, do you accept this request from this app?" check does not apply between two servers. browser → server: CORS applies. server → server: No CORS restrictions. Memorable rule: Servers are a little bit racists, they don't trust browsers but are ok with other servers. This is why the answer to CORS is: a proxy server. Instead of having the app request the image directly from the third-party server, we have it go through our own server first (which we can configure to trust the "everything is good between us" check). This server then passes the request along to the third party. In particular –do you remember we use a 2D graphics library bla bla bla– Assets.load() does accept the raw base64 of the image. So instead of using the fetch() from the library we solved it doing the request ourselves and parsing the image as a base64 blob. async function fetchImageThroughOurProxyServer(url) => { const response = await fetch(url); const arrayBuffer = await response.arrayBuffer(); const base64 = Buffer.from(arrayBuffer).toString('base64'); return `data:image/jpeg;base64,${base64}`; }; async function fetchImage(image) {} const blob = await fetchImageThroughOurProxyServer(image.url); if (!blob) { return null; } const src = URL.createObjectURL(blob); return await Assets.load({ src, alias: image.url, loadParser: 'loadTextures' }); } thanks for reading.

I create apps for a living. Specifically, apps that run on a Set-Top Box –an embedded system with less RAM than a Raspberry Pi– rendering on a TV.
..to put it formally: I create React apps that runs on an ancient browser on top of a '90s' embedded system with lower specs than a Raspberry Pi, displayed on your TV.
yes, it's a challenge.
Right now we're building an 'Amazon'-like app: a grid of products. Using the TV remote you can move through the grid of products.
You get the idea.
Lately we've been playing with WebGL graphics. Using We use Hold on i'm getting there
To load the images, you need first to load on an Asset's cache like: Which is –checked in their GitHub– doing a regular ...
And that, led to CORS error cause CORS –yes there are millions of posts explaining CORS– CORS is expected.
Browsers, before making any request, send a pre-flight request (an If the server doesn’t explicitly allow the request from this "outsider" (i.e., by returning an So, as an app, when I try to request something from a server, the browser ensures that the deal is consented.
The "ey, do you accept this request from this app?" check does not apply between two servers.
Memorable rule: Servers are a little bit racists, they don't trust browsers but are ok with other servers.
This is why the answer to CORS is: a proxy server.
Instead of having the app request the image directly from the third-party server, we have it go through our own server first (which we can configure to trust the "everything is good between us" check). This server then passes the request along to the third party.
In particular –do you remember we use a 2D graphics library bla bla bla– So instead of using the thanks for reading. .path()
.fill()
on a is more perfomant than translating regular
pixi.js
: a –quote– "rendering system that uses WebGL (or optionally Canvas) to display images and other 2D visual content".
import { Assets } from 'pixi.js';
await Assets.load({
src: image.url,
alias: image.url,
loadParser: 'loadTextures',
});
GET
using fetch()
.
Assets.load({ src })
is trying to fetch the resource from a server from a third party. And i have no control over this server.
CORS strikes back
HTTP OPTIONS
) asking the server: "ey buddy, I’d like to request this resource from you, and I’m from this origin, which is different from yours. is ok?"
Access-Control-Allow-Origin header
with the origin it agrees to), the browser itself blocks the request.
How to solve CORS
Assets.load()
does accept the raw base64 of the image.
fetch()
from the library we solved it doing the request ourselves and parsing the image as a base64 blob.
async function fetchImageThroughOurProxyServer(url) => {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const base64 = Buffer.from(arrayBuffer).toString('base64');
return `data:image/jpeg;base64,${base64}`;
};
async function fetchImage(image) {}
const blob = await fetchImageThroughOurProxyServer(image.url);
if (!blob) {
return null;
}
const src = URL.createObjectURL(blob);
return await Assets.load({ src, alias: image.url, loadParser: 'loadTextures' });
}