-1

Im building a webapp using Angular4 that is supposed, among other things, to playback audio files. Unfortunately i have no control over the server serving the media files and therefore can't modify the server settings.

When i now create an audio element and play it directly, the audio playback works as expected:

var audio = new Audio();
audio.src = item.url; // the item is simply an object that holds the url and title
audio.load();
audio.play();

When i now use a player-class that encapsulates the playback functionality i get a CORS error since the mp3 items don't have the appropiate headers set:

@Injectable
export class Player {
audio: any;

constructor(private zone: NgZone){
    this.initialize();
}

initialize(){
    if (!this.audio) {
        this.audio = new Audio();
        this.audio.autoplay.false;
        this.audio.preload = 'auto';
        this.audio.autobuffer = true;
        this.audio.crossOrigin = "anonymous";
    }
}

setUrl(url: string) {
    this.initialize();
    this.audio.pause();
    this.audio.src = url;
    this.audio.load();
}

play() {
    this.audio.play();
}

pause() {
    this.audio.pause();
}

}

The error message that is returned upon play is the following, which essentially inidactes that the CORS policy prevents the item from being played:

Uncaught (in promise) DOMException: Failed to load because no supported source was found.

Is there any way to work around this? And why does it work when i call the audio element directly in the controller?

Ploppy
  • 14,810
  • 6
  • 41
  • 58
narain
  • 392
  • 5
  • 18

1 Answers1

0

Basically CORS is a limitation imposed and controller by the web browsers that prevents to load or retrieve cross source content using AJAX requests, so a possible solutions is to read and stream the mp3 using a server side solution.

A workaround is for example to develop a proxy server that relays the mp3 streams without the CORS limitation. You can achieve that using for example NodeJS.

You can create a proxy using for the CORS anywhere package: https://www.npmjs.com/package/cors-anywhere

or you can also develop your custom proxy and to use the CORS middleware: https://github.com/expressjs/cors

So the workaround should looks like:

┌─────────────────┐     ┌───────────────────────┐      ┌────────────┐
│   MP3 HOSTING   │     │      YOUR PROXY       │      │            │
│(CORS LIMITATION)│───▶ │ (NO CORS LIMITATION)  │────▶ │Your WebAPP │
│                 │     │                       │      │            │
└─────────────────┘     └───────────────────────┘      └────────────┘

Regarding to the reason about why your first example worked is because sometimes the browser is "smart enough" to distinguish when a content is loaded in fair way without any security implication so CORS policy is ignored (For more details see: https://stackoverflow.com/a/41308074/1641558).

Community
  • 1
  • 1
Juan Lago
  • 960
  • 1
  • 10
  • 20