mirror of
https://github.com/zhigang1992/AndroidVideoCache.git
synced 2026-03-28 07:48:46 +08:00
tests for url redirections
This commit is contained in:
@@ -12,7 +12,7 @@ repositories {
|
||||
maven { url 'https://dl.bintray.com/alexeydanilov/maven' }
|
||||
}
|
||||
dependencies {
|
||||
compile 'com.danikula:videocache:2.0.9'
|
||||
compile 'com.danikula:videocache:2.1.0'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ publish {
|
||||
userOrg = 'alexeydanilov'
|
||||
groupId = 'com.danikula'
|
||||
artifactId = 'videocache'
|
||||
publishVersion = '2.0.9'
|
||||
publishVersion = '2.1.0'
|
||||
description = 'Cache support for android VideoView'
|
||||
website = 'https://github.com/danikula/AndroidVideoCache'
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.danikula.videocache;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -11,8 +12,11 @@ import java.net.URL;
|
||||
|
||||
import static com.danikula.videocache.ProxyCacheUtils.DEFAULT_BUFFER_SIZE;
|
||||
import static com.danikula.videocache.ProxyCacheUtils.LOG_TAG;
|
||||
import static java.net.HttpURLConnection.HTTP_MOVED_PERM;
|
||||
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
import static java.net.HttpURLConnection.HTTP_PARTIAL;
|
||||
import static java.net.HttpURLConnection.HTTP_SEE_OTHER;
|
||||
|
||||
/**
|
||||
* {@link Source} that uses http resource as source for {@link ProxyCache}.
|
||||
@@ -21,7 +25,8 @@ import static java.net.HttpURLConnection.HTTP_PARTIAL;
|
||||
*/
|
||||
public class HttpUrlSource implements Source {
|
||||
|
||||
public String url;
|
||||
private static final int MAX_REDIRECTS = 5;
|
||||
public final String url;
|
||||
private HttpURLConnection connection;
|
||||
private InputStream inputStream;
|
||||
private volatile int available = Integer.MIN_VALUE;
|
||||
@@ -47,33 +52,10 @@ public class HttpUrlSource implements Source {
|
||||
@Override
|
||||
public void open(int offset) throws ProxyCacheException {
|
||||
try {
|
||||
boolean isRedirected;
|
||||
int redirectCount = 0;
|
||||
int responseCode;
|
||||
do {
|
||||
Log.d(ProxyCacheUtils.LOG_TAG, "Open connection " + (offset > 0 ? " with offset " + offset : "") + " to " + url);
|
||||
connection = (HttpURLConnection) new URL(url).openConnection();
|
||||
if (offset > 0) {
|
||||
connection.setRequestProperty("Range", "bytes=" + offset + "-");
|
||||
}
|
||||
responseCode = connection.getResponseCode();
|
||||
if ((responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
||||
|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP
|
||||
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER)) {
|
||||
url = connection.getHeaderField("Location");
|
||||
isRedirected = true;
|
||||
redirectCount++;
|
||||
} else {
|
||||
isRedirected = false;
|
||||
}
|
||||
if (redirectCount > ProxyCacheUtils.MAX_REDIRECTS) {
|
||||
throw new ProxyCacheException("Too many redirects");
|
||||
}
|
||||
} while (isRedirected);
|
||||
|
||||
connection = openConnection(offset, "GET", -1);
|
||||
mime = connection.getContentType();
|
||||
inputStream = new BufferedInputStream(connection.getInputStream(), DEFAULT_BUFFER_SIZE);
|
||||
available = readSourceAvailableBytes(connection, offset, responseCode);
|
||||
available = readSourceAvailableBytes(connection, offset, connection.getResponseCode());
|
||||
} catch (IOException e) {
|
||||
throw new ProxyCacheException("Error opening connection for " + url + " with offset " + offset, e);
|
||||
}
|
||||
@@ -111,28 +93,7 @@ public class HttpUrlSource implements Source {
|
||||
HttpURLConnection urlConnection = null;
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
boolean isRedirected;
|
||||
int redirectCount = 0;
|
||||
do {
|
||||
urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setConnectTimeout(10000);
|
||||
urlConnection.setReadTimeout(10000);
|
||||
urlConnection.setRequestMethod("HEAD");
|
||||
int responseCode = urlConnection.getResponseCode();
|
||||
if ((responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
||||
|| responseCode == HttpURLConnection.HTTP_MOVED_TEMP
|
||||
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER)) {
|
||||
url = urlConnection.getHeaderField("Location");
|
||||
isRedirected = true;
|
||||
redirectCount++;
|
||||
} else {
|
||||
isRedirected = false;
|
||||
}
|
||||
if (redirectCount > ProxyCacheUtils.MAX_REDIRECTS) {
|
||||
throw new ProxyCacheException("Too many redirects");
|
||||
}
|
||||
} while (isRedirected);
|
||||
|
||||
urlConnection = openConnection(0, "HEAD", 10000);
|
||||
available = urlConnection.getContentLength();
|
||||
mime = urlConnection.getContentType();
|
||||
inputStream = urlConnection.getInputStream();
|
||||
@@ -147,6 +108,36 @@ public class HttpUrlSource implements Source {
|
||||
}
|
||||
}
|
||||
|
||||
private HttpURLConnection openConnection(int offset, String method, int timeout) throws IOException, ProxyCacheException {
|
||||
HttpURLConnection connection;
|
||||
boolean redirected;
|
||||
int redirectCount = 0;
|
||||
String url = this.url;
|
||||
do {
|
||||
Log.d(LOG_TAG, "Open connection " + (offset > 0 ? " with offset " + offset : "") + " to " + url);
|
||||
connection = (HttpURLConnection) new URL(url).openConnection();
|
||||
connection.setRequestMethod(method);
|
||||
if (offset > 0) {
|
||||
connection.setRequestProperty("Range", "bytes=" + offset + "-");
|
||||
}
|
||||
if (timeout > 0) {
|
||||
connection.setConnectTimeout(timeout);
|
||||
connection.setReadTimeout(timeout);
|
||||
}
|
||||
int code = connection.getResponseCode();
|
||||
redirected = code == HTTP_MOVED_PERM || code == HTTP_MOVED_TEMP || code == HTTP_SEE_OTHER;
|
||||
if (redirected) {
|
||||
url = connection.getHeaderField("Location");
|
||||
redirectCount++;
|
||||
connection.disconnect();
|
||||
}
|
||||
if (redirectCount > MAX_REDIRECTS) {
|
||||
throw new ProxyCacheException("Too many redirects: " + redirectCount);
|
||||
}
|
||||
} while (redirected);
|
||||
return connection;
|
||||
}
|
||||
|
||||
public synchronized String getMime() throws ProxyCacheException {
|
||||
if (TextUtils.isEmpty(mime)) {
|
||||
fetchContentInfo();
|
||||
@@ -154,6 +145,10 @@ public class HttpUrlSource implements Source {
|
||||
return mime;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HttpUrlSource{url='" + url + "}";
|
||||
|
||||
@@ -25,7 +25,6 @@ class ProxyCacheUtils {
|
||||
static final String LOG_TAG = "ProxyCache";
|
||||
static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
|
||||
static final int MAX_ARRAY_PREVIEW = 16;
|
||||
static final int MAX_REDIRECTS = 5;
|
||||
|
||||
static String getSupposablyMime(String url) {
|
||||
MimeTypeMap mimes = MimeTypeMap.getSingleton();
|
||||
|
||||
@@ -17,7 +17,7 @@ apply plugin: 'com.neenbedankt.android-apt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion '23.0.0'
|
||||
buildToolsVersion '23.0.1'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.danikula.videocache.sample"
|
||||
@@ -37,9 +37,9 @@ apt {
|
||||
|
||||
dependencies {
|
||||
// compile project(':library')
|
||||
compile 'com.android.support:support-v4:23.0.0'
|
||||
compile 'com.android.support:support-v4:23.0.1'
|
||||
compile 'org.androidannotations:androidannotations-api:3.3.2'
|
||||
compile 'com.danikula:videocache:2.0.9'
|
||||
compile 'com.danikula:videocache:2.1.0'
|
||||
compile 'com.viewpagerindicator:library:2.4.2-SNAPSHOT@aar'
|
||||
apt 'org.androidannotations:androidannotations:3.3.2'
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.danikula.videocache.support.ProxyCacheTestUtils.ASSETS_DATA_BI
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.ASSETS_DATA_NAME;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_BIG_SIZE;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_BIG_URL;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_BIG_URL_ONE_REDIRECT;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_URL;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.getFileContent;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.loadAssetFile;
|
||||
@@ -81,6 +82,20 @@ public class HttpProxyCacheServerTest {
|
||||
assertThat(response.second.data).isEqualTo(loadAssetFile(ASSETS_DATA_BIG_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyFullResponseWithRedirect() throws Exception {
|
||||
Pair<File, Response> response = readProxyData(HTTP_DATA_BIG_URL_ONE_REDIRECT);
|
||||
|
||||
assertThat(response.second.code).isEqualTo(200);
|
||||
assertThat(response.second.contentLength).isEqualTo(HTTP_DATA_BIG_SIZE);
|
||||
assertThat(response.second.contentType).isEqualTo("image/jpeg");
|
||||
assertThat(response.second.headers.containsKey("Accept-Ranges")).isTrue();
|
||||
assertThat(response.second.headers.get("Accept-Ranges").get(0)).isEqualTo("bytes");
|
||||
assertThat(response.second.headers.containsKey("Content-Range")).isFalse();
|
||||
assertThat(response.second.data).isEqualTo(getFileContent(response.first));
|
||||
assertThat(response.second.data).isEqualTo(loadAssetFile(ASSETS_DATA_BIG_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyPartialResponse() throws Exception {
|
||||
int offset = 42000;
|
||||
@@ -99,6 +114,24 @@ public class HttpProxyCacheServerTest {
|
||||
assertThat(getFileContent(response.first)).isEqualTo(loadAssetFile(ASSETS_DATA_BIG_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyPartialResponseWithRedirect() throws Exception {
|
||||
int offset = 42000;
|
||||
Pair<File, Response> response = readProxyData(HTTP_DATA_BIG_URL_ONE_REDIRECT, offset);
|
||||
|
||||
assertThat(response.second.code).isEqualTo(206);
|
||||
assertThat(response.second.contentLength).isEqualTo(HTTP_DATA_BIG_SIZE - offset);
|
||||
assertThat(response.second.contentType).isEqualTo("image/jpeg");
|
||||
assertThat(response.second.headers.containsKey("Accept-Ranges")).isTrue();
|
||||
assertThat(response.second.headers.get("Accept-Ranges").get(0)).isEqualTo("bytes");
|
||||
assertThat(response.second.headers.containsKey("Content-Range")).isTrue();
|
||||
String rangeHeader = String.format("bytes %d-%d/%d", offset, HTTP_DATA_BIG_SIZE, HTTP_DATA_BIG_SIZE);
|
||||
assertThat(response.second.headers.get("Content-Range").get(0)).isEqualTo(rangeHeader);
|
||||
byte[] expectedData = Arrays.copyOfRange(loadAssetFile(ASSETS_DATA_BIG_NAME), offset, HTTP_DATA_BIG_SIZE);
|
||||
assertThat(response.second.data).isEqualTo(expectedData);
|
||||
assertThat(getFileContent(response.first)).isEqualTo(loadAssetFile(ASSETS_DATA_BIG_NAME));
|
||||
}
|
||||
|
||||
private Pair<File, Response> readProxyData(String url, int offset) throws IOException {
|
||||
File externalCacheDir = RuntimeEnvironment.application.getExternalCacheDir();
|
||||
FileNameGenerator fileNameGenerator = new Md5FileNameGenerator(externalCacheDir);
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
package com.danikula.videocache;
|
||||
|
||||
import com.danikula.videocache.test.BuildConfig;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.ASSETS_DATA_BIG_NAME;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.ASSETS_DATA_NAME;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_BIG_SIZE;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_BIG_URL;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_SIZE;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_URL;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_URL_3_REDIRECTS;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_URL_6_REDIRECTS;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.HTTP_DATA_URL_ONE_REDIRECT;
|
||||
import static com.danikula.videocache.support.ProxyCacheTestUtils.loadAssetFile;
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.fest.assertions.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Alexey Danilov (danikula@gmail.com).
|
||||
@@ -59,15 +66,68 @@ public class HttpUrlSourceTest {
|
||||
assertThat(source.available()).isEqualTo(loadAssetFile(ASSETS_DATA_NAME).length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchInfoWithRedirect() throws Exception {
|
||||
HttpUrlSource source = new HttpUrlSource(HTTP_DATA_URL_ONE_REDIRECT);
|
||||
source.open(0);
|
||||
int available = source.available();
|
||||
String mime = source.getMime();
|
||||
source.close();
|
||||
|
||||
assertThat(available).isEqualTo(HTTP_DATA_SIZE);
|
||||
assertThat(mime).isEqualTo("image/jpeg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchDataWithRedirect() throws Exception {
|
||||
HttpUrlSource source = new HttpUrlSource(HTTP_DATA_URL_ONE_REDIRECT);
|
||||
source.open(0);
|
||||
byte[] readData = new byte[HTTP_DATA_SIZE];
|
||||
source.read(readData);
|
||||
source.close();
|
||||
|
||||
byte[] expectedData = Arrays.copyOfRange(loadAssetFile(ASSETS_DATA_NAME), 0, HTTP_DATA_SIZE);
|
||||
assertThat(readData).isEqualTo(expectedData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchPartialDataWithRedirect() throws Exception {
|
||||
int offset = 42;
|
||||
HttpUrlSource source = new HttpUrlSource(HTTP_DATA_URL_ONE_REDIRECT);
|
||||
source.open(offset);
|
||||
byte[] readData = new byte[HTTP_DATA_SIZE - offset];
|
||||
source.read(readData);
|
||||
source.close();
|
||||
|
||||
byte[] expectedData = Arrays.copyOfRange(loadAssetFile(ASSETS_DATA_NAME), offset, HTTP_DATA_SIZE);
|
||||
assertThat(readData).isEqualTo(expectedData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchPartialDataWithMultiRedirects() throws Exception {
|
||||
int offset = 42;
|
||||
HttpUrlSource source = new HttpUrlSource(HTTP_DATA_URL_3_REDIRECTS);
|
||||
source.open(offset);
|
||||
byte[] readData = new byte[HTTP_DATA_SIZE - offset];
|
||||
source.read(readData);
|
||||
source.close();
|
||||
|
||||
byte[] expectedData = Arrays.copyOfRange(loadAssetFile(ASSETS_DATA_NAME), offset, HTTP_DATA_SIZE);
|
||||
assertThat(readData).isEqualTo(expectedData);
|
||||
}
|
||||
|
||||
@Ignore("To test it fairly we should disable caching connection.setUseCaches(false), but it will decrease performance")
|
||||
@Test(expected = ProxyCacheException.class)
|
||||
public void testExceedingRedirects() throws Exception {
|
||||
HttpUrlSource source = new HttpUrlSource(HTTP_DATA_URL_6_REDIRECTS);
|
||||
source.open(0);
|
||||
fail("Too many redirects");
|
||||
}
|
||||
|
||||
@Ignore("Seems Robolectric bug: MimeTypeMap.getFileExtensionFromUrl always returns null")
|
||||
@Test
|
||||
public void testMimeByUrl() throws Exception {
|
||||
assertThat(new HttpUrlSource("http://mysite.by/video.mp4").getMime()).isEqualTo("video/mp4");
|
||||
assertThat(new HttpUrlSource(HTTP_DATA_URL).getMime()).isEqualTo("image/jpeg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpUrlSourceRedirect() throws Exception {
|
||||
assertThat(new HttpUrlSource("http://goo.gl/K0gWQW").getMime()).isEqualTo("video/mp4");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@ import java.util.UUID;
|
||||
public class ProxyCacheTestUtils {
|
||||
|
||||
public static final String HTTP_DATA_URL = "https://dl.dropboxusercontent.com/u/15506779/persistent/proxycache/android.jpg";
|
||||
public static final String HTTP_DATA_URL_ONE_REDIRECT = "http://bit.ly/1V5PeY5";
|
||||
public static final String HTTP_DATA_URL_3_REDIRECTS = "http://bit.ly/1KvVmgZ";
|
||||
public static final String HTTP_DATA_URL_6_REDIRECTS = "http://ow.ly/SugRH";
|
||||
public static final String HTTP_DATA_BIG_URL = "https://dl.dropboxusercontent.com/u/15506779/persistent/proxycache/phones.jpg";
|
||||
public static final String HTTP_DATA_BIG_URL_ONE_REDIRECT = "http://bit.ly/1iJ69yA";
|
||||
public static final String ASSETS_DATA_NAME = "android.jpg";
|
||||
public static final String ASSETS_DATA_BIG_NAME = "phones.jpg";
|
||||
public static final int HTTP_DATA_SIZE = 4768;
|
||||
|
||||
Reference in New Issue
Block a user