Recently i have been building a streaming app which i just feed in an m3u8 playlist and be able to stream some hls content. The problem i have faced is most of the m3u8 playlist i came across are geo-blocked or they were suddenly giving me the cors issue.
What is the Cors Anyway?.
Cross-origin resource sharing (CORS) is a mechanism for integrating applications. CORS defines a way for client web applications that are loaded in one domain to interact with resources in a different domain. This is useful because complex applications often reference third-party APIs and resources in their client-side code. For example, your application may use your browser to pull videos from a video platform API, use fonts from a public font library, or display weather data from a national weather database. CORS allows the client browser to check with the third-party servers if the request is authorized before any data transfers.
Why is Cors even important?.
In the past, when internet technologies were still new, cross-site request forgery (CSRF) issues happened. These issues sent fake client requests from the victim's browser to another application.
For example, the victim logged into their bank's application. Then they were tricked into loading an external website on a new browser tab. The external website then used the victim's cookie credentials and relayed data to the bank application while pretending to be the victim. Unauthorized users then had unintended access to the bank application.
To prevent such CSRF issues, all browsers now implement the same-origin policy
Can Cors even be unblocked?.
After days of scrabbing the internet, i found 3 possible ways anyone could surely avoid getting hit by the cors issue.
- Using a browser extension
- Using the cors-anywhere proxy
- Building your own proxy
1. Using a browser extension
There are many browser extensions out there like Access Control-Allow-Origin - Unblock that you install in your browser, enable it and you see your cors problem disappear magically.
The browser extension solution proved to be my solution until i pushed an mvp to production, tried to do streams and nothing was working at all.
The browser extension tends to work for you while in development phase however once you push to production, the browser extension can nologer trick the browser with fake headers.
2. Using a cors-anywhere proxy
You can’t ask your users to trick their browsers by installing a plugin that applies an header in the frontend. But you can control the backend address that the web app’s API requests are going to.
The cors-anywhere server is a proxy that adds CORS headers to a request. A proxy acts as an intermediary between a client and server. In this case, the cors-anywhere proxy server operates in between the frontend web app making the request, and the server that responds with data. Similar to the Allow-control-allow-origin plugin, it adds the more open Access-Control-Allow-Origin: * header to the response.
It works like this. Say your frontend is trying to make a GET request to:
https://joke-api-strict-cors.appspot.com/jokes/random
But this api does not have a Access-Control-Allow-Origin value in place that permits the web application domain to access it. So instead, send your GET request to:
https://cors-anywhere.herokuapp.com/https://joke-api-strict-cors.appspot.com/jokes/random
The proxy server receives the https://joke-api-strict-cors.appspot.com/jokes/random
from the url above. Then it makes the request to get that server’s response. And finally, the proxy applies the Access-Control-Allow-Origin: * to that original response.
This solution is great because it works in both development and production. In summary, you’re taking advantage of the fact that the same origin policy is only implemented in browser-to-server communication. Which means it doesn’t have to be enforced in server-to-server communication!
The one downside of the cors-anywhere proxy is that can often take a while to receive a response. The latency is high enough to make your applications appear a bit sluggish.
This brings us to a final, even better approach.
3. Building your own proxy
The fix I recommend in situations like this, is to build your own proxy! Exactly like the previous solution, you’re utilizing the fact that the same origin policy is not enforced within server-to-server communication. In addition, you eliminate the latency concern. You don’t need to share the cors-anywhere proxy with other consumers, and you can dedicate as many resources as you need to your own servers.
Here’s some quick Node.js code that uses the express web framework to create a proxy server around the same https://joke-api-strict-cors.appspot.com/
from above:
const express = require("express");
const request = require("request");
const app = express();
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
next();
});
app.get("/jokes/random", (req, res) => {
request(
{ url: "https://joke-api-strict-cors.appspot.com/jokes/random" },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: "error", message: err.message });
}
res.json(JSON.parse(body));
}
);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
How does this work? The proxy uses express middleware to apply a Access-Control-Allow-Origin: * header to every response from the server. At its own jokes/random GET endpoint, the proxy requests a random joke from another server. The same-origin policy doesn’t step in to block the request, even though the domains are different.
After all, this is a server-to-server request. Finally, the proxy creates a response to the original requester (an app on the browser) consisting of the resulting data and the middleware-applied Access-Control-Allow-Origin: * header.
Conclusion
The CORS error can be the bane of the frontend developer. But once you understand the underlying same-origin policy behind the error, and how it fights the malicious cross-site request forgery attack, it becomes a little more bearable.
Ultimately, with these fixes, you’ll never have to break a sweat over seeing that red CORS error in your browser console logs again. Instead, in its face, you’ll whip out the plugin or a proxy, and exclaim: