Hls.js: xhrSetup function not working with async/await

Created on 19 Sep 2017  路  10Comments  路  Source: video-dev/hls.js

Environment

  • [x] The stream has correct Access-Control-Allow-Origin headers (CORS)
  • [x] There are no network errors such as 404s in the browser console when trying to play the stream
  • [x] The issue observed is not already reported by searching on Github under https://github.com/video-dev/hls.js/issues
  • [] The issue occurs in the latest reference client on http://video-dev.github.io/hls.js/demo and not just on my page
  • Link to playable M3U8 file: -
  • Hls.js version: 0.7.11
  • Browser name/version: Chrome 64bit 60.0.3112.113
  • OS name/version: MacOS Sierra 10.12.5
Steps to reproduce
  1. Please provide clear steps to reproduce your problem
  2. Whenever possible, share a demo/example page which reproduces the problem you are having with the least amount of code possible.
  3. If the bug is intermittent, give a rough frequency if possible
Expected behavior

What you expected to happen
Playing stream.

Actual behavior

What actually happened
Stream not playing.

Console output
Uncaught (in promise) DOMException: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.

Hi. I have a problem with xhrSetup function in hls.js API.
I have async function to get access token and then i want paste access token to request header called Authorization. Now when i'm try to do this i get an error:

Uncaught (in promise) DOMException: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.

This is code example:

xhrSetup: async (xhr, url) => {
   const accessToken = await getAccessToken()

   xhr.setRequestHeader('Authorization', `Bearer ${accessToken}`)
}

I think problem in this file, because function is not async: https://github.com/video-dev/hls.js/blob/master/src/utils/xhr-loader.js

Most helpful comment

I think your use case is too specific.
It always possible to design a solution and handle asynchronous behavior outside of the library.
I see how the change is more convenient for you but I don't see how such change is more generic for a majority of the library users.
I think it's unnecessary to introduce async/await polyfill to the project to solve a narrow use-case.

All 10 comments

xhr.setRequestHeader expects xhr.readyState === OPEN
you can try manually opening xhr before setting headers

xhrSetup: async (xhr, url) => {
   const accessToken = await getAccessToken()
   xhr.open('GET', url, true);
   xhr.setRequestHeader('Authorization', `Bearer ${accessToken}`)
}

It's not working too, because request is already done (200 code) when i'm try to set request header with my accessToken.
When i add this xhr.open('GET', url, true); my request to manifest is canceled.

xhrSetup() is not expected to be async
you might need to completely rewrite / override existing xhrLoader

I created a pull request (https://github.com/video-dev/hls.js/pull/1361) to show you what i want to change. It's working for my case and standard usage of xhrSetup not broken. Since i'm using async/await, i need to add babel-preset-stage-0 and babel-pollyfill, but i don't know it's good or not.
Can you offer a better solution ?

I think your use case is too specific.
It always possible to design a solution and handle asynchronous behavior outside of the library.
I see how the change is more convenient for you but I don't see how such change is more generic for a majority of the library users.
I think it's unnecessary to introduce async/await polyfill to the project to solve a narrow use-case.

Ok, i understand you. XHR is old way to get via http. I found this in your repository - https://github.com/video-dev/hls.js/blob/master/src/utils/fetch-loader.js
I don't understand why you don't use it, i think it's suitable for me, because in this case uses promises.
Maybe we think about to rewrite xhr-loader to fetch way ?

@PidginEnemy I think we use XHR because you can't abort fetch.

yes, we can't abort Fetch

@PidginEnemy i would suggest you to use the following as I agree with @NicolasSiver that it is unnecessary to change xhrSetup() API for a narrow use-case

class myLoader extends Hls.DefaultConfig.loader {
  loadInternal() {
    // existing loadInternal, either using xhrSetup() with async/await or hardcoding your own biz logic

  }
}

@mangui thanks for your solution, i'l try this.

closing as no plan to change xhr-loader API in the short term

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fredvb picture fredvb  路  3Comments

PeterBassemYoussef picture PeterBassemYoussef  路  3Comments

sbrez picture sbrez  路  3Comments

ronag picture ronag  路  4Comments

nickcartery picture nickcartery  路  4Comments