Commit 412db200 by ibaker Committed by Ian Baker

Propagate HTTP request headers through CacheDataSource

This has been broken since
https://github.com/google/ExoPlayer/commit/c3d6be3afdd7c0ca68dba15e443bc64aa3f61073
and broken for ICY (where I noticed the problem) since
https://github.com/google/ExoPlayer/commit/5695bae9d8fde5e156fd38fa552e266c5611c71f.
ICY symptom is that we see no repeated metadata, because the
Icy-MetaData:1 header doesn't make it to the server so we never get back
icy-metaint.

PiperOrigin-RevId: 285379234
parent a39e6790
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
[Span-styled text]( https://developer.android.com/guide/topics/text/spans) [Span-styled text]( https://developer.android.com/guide/topics/text/spans)
(e.g. subtitles). (e.g. subtitles).
* Add `Player.getCurrentLiveOffset` to conveniently return the live offset. * Add `Player.getCurrentLiveOffset` to conveniently return the live offset.
* Propagate HTTP request headers through `CacheDataSource`.
### 2.11.0 (2019-12-11) ### ### 2.11.0 (2019-12-11) ###
......
...@@ -138,7 +138,8 @@ public final class CacheDataSource implements DataSource { ...@@ -138,7 +138,8 @@ public final class CacheDataSource implements DataSource {
@Nullable private Uri actualUri; @Nullable private Uri actualUri;
@HttpMethod private int httpMethod; @HttpMethod private int httpMethod;
@Nullable private byte[] httpBody; @Nullable private byte[] httpBody;
private int flags; private Map<String, String> httpRequestHeaders = Collections.emptyMap();
@DataSpec.Flags private int flags;
@Nullable private String key; @Nullable private String key;
private long readPosition; private long readPosition;
private long bytesRemaining; private long bytesRemaining;
...@@ -263,6 +264,7 @@ public final class CacheDataSource implements DataSource { ...@@ -263,6 +264,7 @@ public final class CacheDataSource implements DataSource {
actualUri = getRedirectedUriOrDefault(cache, key, /* defaultUri= */ uri); actualUri = getRedirectedUriOrDefault(cache, key, /* defaultUri= */ uri);
httpMethod = dataSpec.httpMethod; httpMethod = dataSpec.httpMethod;
httpBody = dataSpec.httpBody; httpBody = dataSpec.httpBody;
httpRequestHeaders = dataSpec.httpRequestHeaders;
flags = dataSpec.flags; flags = dataSpec.flags;
readPosition = dataSpec.position; readPosition = dataSpec.position;
...@@ -353,6 +355,10 @@ public final class CacheDataSource implements DataSource { ...@@ -353,6 +355,10 @@ public final class CacheDataSource implements DataSource {
actualUri = null; actualUri = null;
httpMethod = DataSpec.HTTP_METHOD_GET; httpMethod = DataSpec.HTTP_METHOD_GET;
httpBody = null; httpBody = null;
httpRequestHeaders = Collections.emptyMap();
flags = 0;
readPosition = 0;
key = null;
notifyBytesRead(); notifyBytesRead();
try { try {
closeCurrentSource(); closeCurrentSource();
...@@ -399,7 +405,15 @@ public final class CacheDataSource implements DataSource { ...@@ -399,7 +405,15 @@ public final class CacheDataSource implements DataSource {
nextDataSource = upstreamDataSource; nextDataSource = upstreamDataSource;
nextDataSpec = nextDataSpec =
new DataSpec( new DataSpec(
uri, httpMethod, httpBody, readPosition, readPosition, bytesRemaining, key, flags); uri,
httpMethod,
httpBody,
readPosition,
readPosition,
bytesRemaining,
key,
flags,
httpRequestHeaders);
} else if (nextSpan.isCached) { } else if (nextSpan.isCached) {
// Data is cached, read from cache. // Data is cached, read from cache.
Uri fileUri = Uri.fromFile(nextSpan.file); Uri fileUri = Uri.fromFile(nextSpan.file);
...@@ -408,6 +422,8 @@ public final class CacheDataSource implements DataSource { ...@@ -408,6 +422,8 @@ public final class CacheDataSource implements DataSource {
if (bytesRemaining != C.LENGTH_UNSET) { if (bytesRemaining != C.LENGTH_UNSET) {
length = Math.min(length, bytesRemaining); length = Math.min(length, bytesRemaining);
} }
// Deliberately skip the HTTP-related parameters since we're reading from the cache, not
// making an HTTP request.
nextDataSpec = new DataSpec(fileUri, readPosition, filePosition, length, key, flags); nextDataSpec = new DataSpec(fileUri, readPosition, filePosition, length, key, flags);
nextDataSource = cacheReadDataSource; nextDataSource = cacheReadDataSource;
} else { } else {
...@@ -422,7 +438,16 @@ public final class CacheDataSource implements DataSource { ...@@ -422,7 +438,16 @@ public final class CacheDataSource implements DataSource {
} }
} }
nextDataSpec = nextDataSpec =
new DataSpec(uri, httpMethod, httpBody, readPosition, readPosition, length, key, flags); new DataSpec(
uri,
httpMethod,
httpBody,
readPosition,
readPosition,
length,
key,
flags,
httpRequestHeaders);
if (cacheWriteDataSource != null) { if (cacheWriteDataSource != null) {
nextDataSource = cacheWriteDataSource; nextDataSource = cacheWriteDataSource;
} else { } else {
......
...@@ -34,6 +34,8 @@ import com.google.android.exoplayer2.util.Util; ...@@ -34,6 +34,8 @@ import com.google.android.exoplayer2.util.Util;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.NavigableSet; import java.util.NavigableSet;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
...@@ -48,20 +50,27 @@ public final class CacheDataSourceTest { ...@@ -48,20 +50,27 @@ public final class CacheDataSourceTest {
private static final int CACHE_FRAGMENT_SIZE = 3; private static final int CACHE_FRAGMENT_SIZE = 3;
private static final String DATASPEC_KEY = "dataSpecKey"; private static final String DATASPEC_KEY = "dataSpecKey";
// Test data
private Uri testDataUri; private Uri testDataUri;
private Map<String, String> httpRequestHeaders;
private DataSpec unboundedDataSpec; private DataSpec unboundedDataSpec;
private DataSpec boundedDataSpec; private DataSpec boundedDataSpec;
private DataSpec unboundedDataSpecWithKey; private DataSpec unboundedDataSpecWithKey;
private DataSpec boundedDataSpecWithKey; private DataSpec boundedDataSpecWithKey;
private String defaultCacheKey; private String defaultCacheKey;
private String customCacheKey; private String customCacheKey;
// Dependencies of SUT
private CacheKeyFactory cacheKeyFactory; private CacheKeyFactory cacheKeyFactory;
private File tempFolder; private File tempFolder;
private SimpleCache cache; private SimpleCache cache;
private FakeDataSource upstreamDataSource;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
testDataUri = Uri.parse("https://www.test.com/data"); testDataUri = Uri.parse("https://www.test.com/data");
httpRequestHeaders = new HashMap<>();
httpRequestHeaders.put("Test-key", "Test-val");
unboundedDataSpec = buildDataSpec(/* unbounded= */ true, /* key= */ null); unboundedDataSpec = buildDataSpec(/* unbounded= */ true, /* key= */ null);
boundedDataSpec = buildDataSpec(/* unbounded= */ false, /* key= */ null); boundedDataSpec = buildDataSpec(/* unbounded= */ false, /* key= */ null);
unboundedDataSpecWithKey = buildDataSpec(/* unbounded= */ true, DATASPEC_KEY); unboundedDataSpecWithKey = buildDataSpec(/* unbounded= */ true, DATASPEC_KEY);
...@@ -69,9 +78,11 @@ public final class CacheDataSourceTest { ...@@ -69,9 +78,11 @@ public final class CacheDataSourceTest {
defaultCacheKey = CacheUtil.DEFAULT_CACHE_KEY_FACTORY.buildCacheKey(unboundedDataSpec); defaultCacheKey = CacheUtil.DEFAULT_CACHE_KEY_FACTORY.buildCacheKey(unboundedDataSpec);
customCacheKey = "customKey." + defaultCacheKey; customCacheKey = "customKey." + defaultCacheKey;
cacheKeyFactory = dataSpec -> customCacheKey; cacheKeyFactory = dataSpec -> customCacheKey;
tempFolder = tempFolder =
Util.createTempDirectory(ApplicationProvider.getApplicationContext(), "ExoPlayerTest"); Util.createTempDirectory(ApplicationProvider.getApplicationContext(), "ExoPlayerTest");
cache = new SimpleCache(tempFolder, new NoOpCacheEvictor()); cache = new SimpleCache(tempFolder, new NoOpCacheEvictor());
upstreamDataSource = new FakeDataSource();
} }
@After @After
...@@ -112,6 +123,19 @@ public final class CacheDataSourceTest { ...@@ -112,6 +123,19 @@ public final class CacheDataSourceTest {
} }
@Test @Test
public void testPropagatesHttpHeadersUpstream() throws Exception {
CacheDataSource cacheDataSource =
createCacheDataSource(/* setReadException= */ false, /* unknownLength= */ false);
DataSpec dataSpec = buildDataSpec(/* position= */ 2, /* length= */ 5);
cacheDataSource.open(dataSpec);
DataSpec[] upstreamDataSpecs = upstreamDataSource.getAndClearOpenedDataSpecs();
assertThat(upstreamDataSpecs).hasLength(1);
assertThat(upstreamDataSpecs[0].httpRequestHeaders).isEqualTo(this.httpRequestHeaders);
}
@Test
public void testUnsatisfiableRange() throws Exception { public void testUnsatisfiableRange() throws Exception {
// Bounded request but the content length is unknown. This forces all data to be cached but not // Bounded request but the content length is unknown. This forces all data to be cached but not
// the length. // the length.
...@@ -572,9 +596,8 @@ public final class CacheDataSourceTest { ...@@ -572,9 +596,8 @@ public final class CacheDataSourceTest {
@CacheDataSource.Flags int flags, @CacheDataSource.Flags int flags,
CacheDataSink cacheWriteDataSink, CacheDataSink cacheWriteDataSink,
CacheKeyFactory cacheKeyFactory) { CacheKeyFactory cacheKeyFactory) {
FakeDataSource upstream = new FakeDataSource();
FakeData fakeData = FakeData fakeData =
upstream upstreamDataSource
.getDataSet() .getDataSet()
.newDefaultData() .newDefaultData()
.setSimulateUnknownLength(unknownLength) .setSimulateUnknownLength(unknownLength)
...@@ -584,7 +607,7 @@ public final class CacheDataSourceTest { ...@@ -584,7 +607,7 @@ public final class CacheDataSourceTest {
} }
return new CacheDataSource( return new CacheDataSource(
cache, cache,
upstream, upstreamDataSource,
new FileDataSource(), new FileDataSource(),
cacheWriteDataSink, cacheWriteDataSink,
flags, flags,
...@@ -602,6 +625,11 @@ public final class CacheDataSourceTest { ...@@ -602,6 +625,11 @@ public final class CacheDataSourceTest {
private DataSpec buildDataSpec(long position, long length, @Nullable String key) { private DataSpec buildDataSpec(long position, long length, @Nullable String key) {
return new DataSpec( return new DataSpec(
testDataUri, position, length, key, DataSpec.FLAG_ALLOW_CACHE_FRAGMENTATION); testDataUri,
position,
length,
key,
DataSpec.FLAG_ALLOW_CACHE_FRAGMENTATION,
httpRequestHeaders);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment