Plyr: Pass headers to the HTTP reuqest

Created on 11 Jan 2019  路  10Comments  路  Source: sampotts/plyr

It would be a great feature to add basic authentication to the video source.

Passing the credentials directly in the link has been dropped by Chrome and more will follow
so http://userb:[email protected]/elon_musk_riding_horse_backwards.mp4 won't pass the credentials any more.

const options = {
   headers: {
     'Authorization': 'Bearer iaf87h8fhd8idfidf=='
   },
   tooltips: {
    controls: true,
    seek: true
  },
 controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'fullscreen']
};
this.videoPlayer = new Plyr(this.videoPlayerEl.nativeElement, options);

Passing a header to the HTTP request can open all sorts of posibilities for private video streaming

Most helpful comment

Bumps won't speed it up. Someone contributing will though. Use those key strokes for good. I don't think this will be a quick change as it will involve loading the content manually rather than using the browsers in-built logic which opens a whole other can of worms.

All 10 comments

Does your example not achieve the same thing?

headers: { 'Authorization': 'Bearer iaf87h8fhd8idfidf==' },

Headers property doesn't exist in the API. That was just my suggestion of who to do that

bumping this :)

bump :)

bump

bump

bump

Bumps won't speed it up. Someone contributing will though. Use those key strokes for good. I don't think this will be a quick change as it will involve loading the content manually rather than using the browsers in-built logic which opens a whole other can of worms.

Bumps won't speed it up. Someone contributing will though. Use those key strokes for good. I don't think this will be a quick change as it will involve loading the content manually rather than using the browsers in-built logic which opens a whole other can of worms.

Hey, I was able to solve this issue very easily using service workers, basically they act as a proxy and can inject custom headers.. even captures the requests required for playing the video.

Browser sends http requests to load the video (200 or 206) -> proxied by service worker's fetch handler -> add custom header -> Pass it normally without any efforts

Here's the service worker code i used to add an auth header:

File: ServiceWorker.js [register this in your main js file]
```
self.addEventListener("fetch", event => {
if (new URL(event.request.url).origin == "https://www.my_video_endpoint.com/") { //only add header to the endpoint i want
event.respondWith(customHeaderRequestFetch(event));
}
});

function customHeaderRequestFetch(event) {
    const newRequest = new Request(event.request, {
        mode: "cors",
        credentials: "omit",
        //also supports partial content (seeking)
        headers: { 
            range:
                event.request.headers.get("range") != undefined
                    ? event.request.headers.get("range")
                    : "0-",
            Authorization:
                "Bearer " +"xxxABCDEFGHxxx"
        }
    });
    return fetch(newRequest);
}

```

That's the whole code, now just register this service worker, and let the browser and plyr do all the hard work (automatically) :)

Reference: https://developers.google.com/web/fundamentals/primers/service-workers

I would be happy to send a PR but i am not familiar with the project structure yet. Hope anyone can implement this!

Thanks @Ashesh3! https://github.com/sampotts/plyr/issues/1312#issuecomment-677267757
For anyone who using Angular:

  1. Create service worker JS file (e.g. sw.js), place it in some where (e.g. src/assets/js/service-worker/). File content is:
let domainInclude = ''; // Recieve from Component
let authToken = ''; // Recieve from Component

self.addEventListener('install', event => {
  const params = new URL(location);
  domainInclude = params.searchParams.get('include');
  authToken = params.searchParams.get('token');
  const installCompleted = Promise.resolve()
    .then(() => {});
  event.waitUntil(installCompleted);
});

self.addEventListener('activate', event => {
  event.waitUntil(
    self.clients.claim(),
    caches.keys().then((cacheNames) => {
        return Promise.all(
            cacheNames.map((cache) => {
                if (cache !== cacheName) {
                    return caches.delete(cache);
                }
            })
        );
    }));
});

// This function is implement from the guide of @Ashesh3
self.addEventListener('fetch', event => {
  if (event.request.url.includes(domainInclude)) {
    event.respondWith(customHeaderRequestFetch(event));
  }
});

function customHeaderRequestFetch(event) {
  const newRequest = new Request(event.request, {
    mode: "cors",
    credentials: "omit",
    //also supports partial content (seeking)
    headers: {
      range:
        event.request.headers.get("range") != undefined
          ? event.request.headers.get("range")
          : "0-",
      Authorization: authToken
    }
  });
  return fetch(newRequest);
}
  1. Edit file angular.json:
    Path: projects > <your-pj-name> > architect > build > options > assets:
"assets": [
   ..........
  {
      "glob": "**/*",
      "input": "src/assets/js/service-worker/",
      "output": "/"
   }
   ..........
]
  1. Go to your Component, where you want to start Service Worker:
ngOnInit() {
   if ('serviceWorker' in navigator) { // Make sure browser support Service Worker
      navigator.serviceWorker.register(`/sw.js?include=${encodeURIComponent('<URL_MATCHING>')}&token=${<YOUR_TOKEN>}`, {
        scope: '<SCOPE>'
      })
        .then(registration => registration.unregister());
        // SW unregistered still working till page reload, so don't worry.
        // But if you don't unregister here, Component may get stuck when you reload page,
        // because old SW is fetching video and not done yet.
        // In this case, If you stop playing video a while, page can be reload.
    } else {
      window.alert('Browser not support Service Worker.');
    }
}

Note:

  • <URL_MATCHING>: Send to sw.js, using to check matching the endpoint you need to add Headers.
    E.g. /api/video/: If Request URL include /api/video/ then sw.js will adding Headers to the request. (http://backend.local/api/video/aaaaa)
  • <YOUR_TOKEN>: Token send to sw.js for attach to Headers.
  • <SCOPE>: Router link where sw.js will working, e.g. /view-video/ (http://localhost:4200/view-video/aaaaa)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Antonio-Laguna picture Antonio-Laguna  路  3Comments

Zsavajji picture Zsavajji  路  3Comments

TheZoker picture TheZoker  路  4Comments

MTyson picture MTyson  路  3Comments

muuvmuuv picture muuvmuuv  路  3Comments