title: CORS configuration for S3-hosted HLS video in JW Player
body: <p>I'm having trouble casting a self-hosted JW Player video. Here's the relevant reference in the Javascript API for configuring the player.<br>
  <a href="https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/#casting" rel="nofollow noreferrer">https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/#casting</a></p>
  
  <p>Here are some details about my setup:<br>
  1) The video is in HLS streaming format. So the file that I'm passing to the JW Player Javascript API has .m3u8 extension.<br>
  2) The video is hosted on S3.<br>
  3) The video is served through CloudFront.</p>
  
  <p>Here's the code that I use to load the video in JW Player:</p>
  
  <pre><code>&lt;div id="jwplayer"&gt;&lt;/div&gt;
  var playerInstance = jwplayer('jwplayer');
  playerInstance.setup({ 
    file: &lt;cloudfront-path-to-m3u8-file&gt;,
    androidhls: true,
    cast: {},
  });
  </code></pre>
  
  <p>When I use version 7.12.13 of the JW Player Javascript library, here's what I observe:</p>
  
  <p>1) The video loads fine in the browser.<br>
  2) When I try to cast it, I see a spinner in the video in the browser, indicating that it's about to start playing via Chromecast.<br>
  3) The Chromecast looks like it's about to start playing the video on the TV. I see the Chromecast symbol with a spinner, then the video timeline bar.<br>
  4) Within a few seoncds, I see the Chromecast home screen. The video never plays on the TV.<br>
  5) At this point, the video start playing in the browser.<br>
  6) I see the following error message in the browser debug console:</p>
  
  <pre><code>provider.cast.js:1 Error: {code: "session_error", description: 
  "LOAD_FAILED", details: {…}}code: "session_error"description: 
  "LOAD_FAILED"details: {type: "LOAD_FAILED"}__proto__: Object
  d.error @ provider.cast.js:1
  (anonymous) @ cast_sender.js:70
  U.onMessage @ cast_sender.js:76
  M.i @ cast_sender.js:56
  </code></pre>
  
  <p>When I use version 8.6.3 of the JW Player Javascript library, here's what I observe:</p>
  
  <p>1) The video loads fine in the browser.<br>
  2) When I try to cast it, I see a spinner in the video in the browser, indicating that it's about to start playing via Chromecast.<br>
  3) The Chromecast looks like it's about to start playing the video on the TV. I see the Chromecast symbol with a spinner, then the video timeline bar.<br>
  4) After a few seconds, I only see the Chromecast symbol on the TV.<br>
  5) The spinner in the video player in the browser spins indefinitely.<br>
  6) I see the following error message in the browser debug console:</p>
  
  <pre><code>provider.cast.js:10 Uncaught TypeError: Cannot read property 'trigger' of undefined
      at c.&lt;anonymous&gt; (provider.cast.js:10)
      at s (application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3)
      at c.a [as trigger] (application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3)
      at t.error (provider.cast.js:10)
      at cast_sender.js:70
      at U.onMessage (cast_sender.js:76)
      at M.i (cast_sender.js:56)
  (anonymous) @ provider.cast.js:10
  s @ application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3
  a @ application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3
  t.error @ provider.cast.js:10
  (anonymous) @ cast_sender.js:70
  U.onMessage @ cast_sender.js:76
  M.i @ cast_sender.js:56
  </code></pre>
  
  <p>Any ideas about what these errors mean or how to go about debugging this issue?</p>
  
  <p>Note that I ran the above tests in Chrome (version 71.0.3578.98 64-bit) on Ubuntu 14.04. I also tried casting these pages from an Android device, but got the same results.</p>
  
  <p>A few things I've tried:</p>
  
  <ul>
  <li>Configured CORS in S3 bucket to allow access from these domains.  </li>
  <li>Added crossdomain.xml to S3 bucket to allow access from these domains.  </li>
  <li>Invalidating cached objects in CloudFront edges.  </li>
  <li>Clearing browser cache.</li>
  </ul>
  
  <p>In trying to isolate the problem, I also tried the following:</p>
  
  <ul>
  <li>Replace m3u8 file with webm file. I can successfully cast with this setup.</li>
  <li>Replace m3u8 file with mp4 file. I can successfully cast with this setup.</li>
  <li>Replace CloudFront path with direct S3 path. I observe the same problematic behavior I described above (i.e., cannot cast and see errors in the console).</li>
  </ul>
  
  <p>I discovered that changing the CORS configuration for the S3 bucket to allow access from all origins fixes the problem:</p>
  
  <pre><code>&lt;CORSRule&gt;
      &lt;AllowedOrigin&gt;*&lt;/AllowedOrigin&gt;
      &lt;AllowedMethod&gt;GET&lt;/AllowedMethod&gt;
      &lt;AllowedMethod&gt;HEAD&lt;/AllowedMethod&gt;
      &lt;ExposeHeader&gt;ETag&lt;/ExposeHeader&gt;
      &lt;AllowedHeader&gt;*&lt;/AllowedHeader&gt;
  &lt;/CORSRule&gt;
  </code></pre>
  
  <p>However, this is certainly not ideal because it opens up the bucket to access from any domain. I tried to restrict access by explicitly specifying <code>CORSRule</code> blocks for the domain that I use to serve the video player. I also tried adding <code>http://*.jwpcdn.com</code> and <code>https://*.jwpcdn.com</code> as allowed origins, since I believe that's where JWPlayer's Chromecast receiver is hosted.
  <a href="https://support.jwplayer.com/articles/cross-domain-file-loading-reference" rel="nofollow noreferrer">https://support.jwplayer.com/articles/cross-domain-file-loading-reference</a></p>
  
  <p>None of these combinations worked. The only way I could get JW Player to successfully cast the HLS video was to allow access from <strong>all</strong> origins.</p>
  
  <p>Any idea how I can configure CORS to get the desired behavior without sacrificing the privacy of the bucket.</p>
  
  <p>Thanks!</p>