Skip to content

Commit

Permalink
Follow 307/308 POST redirects for license requests
Browse files Browse the repository at this point in the history
I was considering putting this directly in DefaultHttpDataSource, however:

- We'd need to modify at least OkHttpDataSource as well. I'm not sure whether
  Cronet follows this type of redirect automatically or not.
- HttpDataSource instances don't know how they're going to be used, so it's
  probably correct that they behave like the underlying network stack.

Issue: #4108

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192745408
  • Loading branch information
ojw28 committed Apr 16, 2018
1 parent 22b8ab5 commit 0ee3963
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
6 changes: 4 additions & 2 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@
* Add release method to Cache interface.
* Prevent multiple instances of SimpleCache in the same folder.
Previous instance must be released.
* Store redirected URI
([#2360](https://github.com/google/ExoPlayer/issues/2360)).
* Cache redirect URLs
([#2360](https://github.com/google/ExoPlayer/issues/2360)).
* DRM:
* Allow multiple listeners for `DefaultDrmSessionManager`.
* Pass `DrmSessionManager` to `ExoPlayerFactory` instead of `RendererFactory`.
* Change minimum API requirement for CBC and pattern encryption from 24 to 25
([#4022][https://github.com/google/ExoPlayer/issues/4022]).
* Fix handling of 307/308 redirects when making license requests
([#4108](https://github.com/google/ExoPlayer/issues/4108)).
* Removed default renderer time offset of 60000000 from internal player. The
actual renderer timestamp offset can be obtained by listening to
`BaseRenderer.onStreamChanged`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
import com.google.android.exoplayer2.upstream.DataSourceInputStream;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

Expand All @@ -37,6 +39,8 @@
@TargetApi(18)
public final class HttpMediaDrmCallback implements MediaDrmCallback {

private static final int MAX_MANUAL_REDIRECTS = 5;

private final HttpDataSource.Factory dataSourceFactory;
private final String defaultLicenseUrl;
private final boolean forceDefaultLicenseUrl;
Expand Down Expand Up @@ -138,14 +142,46 @@ private static byte[] executePost(HttpDataSource.Factory dataSourceFactory, Stri
dataSource.setRequestProperty(requestProperty.getKey(), requestProperty.getValue());
}
}
DataSpec dataSpec = new DataSpec(Uri.parse(url), data, 0, 0, C.LENGTH_UNSET, null,
DataSpec.FLAG_ALLOW_GZIP);
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
try {
return Util.toByteArray(inputStream);
} finally {
Util.closeQuietly(inputStream);

int manualRedirectCount = 0;
while (true) {
DataSpec dataSpec =
new DataSpec(
Uri.parse(url),
data,
/* absoluteStreamPosition= */ 0,
/* position= */ 0,
/* length= */ C.LENGTH_UNSET,
/* key= */ null,
DataSpec.FLAG_ALLOW_GZIP);
DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
try {
return Util.toByteArray(inputStream);
} catch (InvalidResponseCodeException e) {
// For POST requests, the underlying network stack will not normally follow 307 or 308
// redirects automatically. Do so manually here.
boolean manuallyRedirect =
(e.responseCode == 307 || e.responseCode == 308)
&& manualRedirectCount++ < MAX_MANUAL_REDIRECTS;
url = manuallyRedirect ? getRedirectUrl(e) : null;
if (url == null) {
throw e;
}
} finally {
Util.closeQuietly(inputStream);
}
}
}

private static String getRedirectUrl(InvalidResponseCodeException exception) {
Map<String, List<String>> headerFields = exception.headerFields;
if (headerFields != null) {
List<String> locationHeaders = headerFields.get("Location");
if (locationHeaders != null && !locationHeaders.isEmpty()) {
return locationHeaders.get(0);
}
}
return null;
}

}

0 comments on commit 0ee3963

Please sign in to comment.