google / ExoPlayer

This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
https://developer.android.com/media/media3/exoplayer
Apache License 2.0
21.7k stars 6.02k forks source link

Allow specifying per-item request headers (for playback and downloads) #6166

Open chanbbong opened 5 years ago

chanbbong commented 5 years ago

I have different cookies for each video. so each time new video is loaded, I set DownloadManager with new cookie. defaultHttpDataSourceFactory.getDefaultRequestProperties().set("Cookie", cookieValue); however, I can only download video for the first time. I think DownloadService seems to call DownloadManager only when DownloadService is started for the first time. How do I download video with each different cookie?

ojw28 commented 4 years ago

I don't think we currently support this (you can of course implement your own download functionality, rather than relying on the out-of-the-box components that we provide). Marking this as an enhancement.

ojw28 commented 4 years ago

@marcbaechinger - We should consider whether we want to allow request headers to be specified in MediaItem, and (eventually) whether DownloadRequest should include a MediaItem rather than some of its current fields.

msesma commented 4 years ago

Same problem here. Even if I don't allow the user to download two videos al the same time, the DownloadService only request DownloadManager once, so the second video will use the DownloadManger of the first one and fail because of wrong cookie.

BarryFruitman commented 4 years ago

+1 for specifying headers in a DownloadRequest or MediaItem. Headers are used pretty commonly in authentication schemas and it would be useful to be able to specify them on a per-request basis.

NathanSass commented 4 years ago

+1 I would also like this feature

kschults commented 4 years ago

Hi @ojw28, I'm about to start looking into contributing a fix for this, but wanted to check in first with a couple of questions.

1) Are you already working on this? Or do you already have thoughts about what will be involved in fixing it?

2) Is there anything I need to know about developing on this project, aside from what's in CONTRIBUTING.md?

ojw28 commented 4 years ago

Are you already working on this?

No

Do you already have thoughts about what will be involved in fixing it?

Although not directly what you're trying to achieve, I think a good first step would be to add requestHeaders to MediaItem.PlaybackProperties, and use them in the various MediaSource implementations for playback. It doesn't really make logical sense to support something for downloads and not for playback, so I think this should be done first even if you don't need it yourself.

Then for downloads I think you'll need to:

  1. Add a requestHeaders field to DownloadRequest
  2. Upgrade the database logic in DefaultDownloadIndex to support persisting the headers
  3. Use the headers in the various Downloader implementations

Note that I haven't actually tried any of the above, so I can't really guarantee it's correct or accurate. It's a best guess as to what would be needed.

Is there anything I need to know about developing on this project, aside from what's in CONTRIBUTING.md?

Small changes are preferred to larger ones (i.e., the playback and download pieces suggested above should definitely be separate pull requests, rather than one big one). Other stuff that's probably obvious:

kschults commented 4 years ago

Thanks for the info.

For future questions, is there a better way to ask, or is leaving them here the best place?

ojw28 commented 4 years ago

Here is fine; thanks!

kschults commented 4 years ago

@ojw28 Perhaps there's another way to do this. I had initially tried to solve this problem in my client by using HttpDataSourceFactory with defaultRequestProperties set (as did @chanbbong), but it seemed like the broken link in that chain is that DefaultDownloaderFactory uses the same CacheDataSourceFactory for every download request.

I'm having trouble tracking how the DataSourceFactory that gets passed to a DownloadHelper ends up in the DownloadManager, but it seems like it could be more straightforward to allow the DefaultDownloaderFactory to use different sources?

I was able to hack a solution into place on the client side by extending DefaultDownloaderFactory and rewriting the downloadConstructorHelper via reflection during createDownloader. My thinking here is that there may be a way to formalize this into something that isn't an awful hack.

RemiHin commented 3 years ago

Is there any update on this? I'm running into the problem that I can't download files that require an authentication header.

Mkurbanov commented 3 years ago

it's working. just add DefaultHttpDataSource.Factory to DownloadManager. like this code:

            // Create a factory for reading the data from the network.
            Executor downloadExecutor = Runnable::run;
            DefaultHttpDataSource.Factory defaultHttpDataSourceFac = new DefaultHttpDataSource.Factory();
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("header_param", "header_value");
            defaultHttpDataSourceFac.setDefaultRequestProperties(hashMap);
            // Create the download manager.
            downloadManager = new DownloadManager(
                    context,
                    VideoCache.getDatabaseProvider(context),
                    VideoCache.getCache(context),
                    defaultHttpDataSourceFac,
                    downloadExecutor);
kschults commented 3 years ago

@Mkurbanov That solution is fine if you only need a single header that's the same for all downloads. If you need a different header per-download, this won't work.

ojw28 commented 2 years ago

I've generalized the title to cover the playback case as well as the download case. Note that there is a pending pull request that looks to add this (https://github.com/google/ExoPlayer/pull/7852), although I was concerned at the time that:

  1. For adaptive content, it's unclear to which requests headers should be attached during the playback.
  2. It doesn't handle the need to refresh header content (e.g., authorization tokens that may have expired).
kschults commented 2 years ago

Thanks for the update @ojw28. I'm going to be offline for the next six+ months, so I won't be able to move forward on #7852 until at least late fall, if someone wants to pick it up from me. (Will comment over there as well)