Merge branch 'etag-fix' into 'master'
switch etag cache check to purely client-side Closes #562 See merge request !574
This commit is contained in:
commit
aa2d791531
@ -89,11 +89,6 @@ public class IndexV1Updater extends RepoUpdater {
|
|||||||
if (downloader.isNotFound()) {
|
if (downloader.isNotFound()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (downloader.isCached()) {
|
|
||||||
// The index is unchanged since we last read it. We just mark
|
|
||||||
// everything that came from this repo as being updated.
|
|
||||||
Utils.debugLog(TAG, "Repo index for " + dataUri + " is up to date (by etag)");
|
|
||||||
}
|
|
||||||
hasChanged = downloader.hasChanged();
|
hasChanged = downloader.hasChanged();
|
||||||
|
|
||||||
if (!hasChanged) {
|
if (!hasChanged) {
|
||||||
|
@ -132,12 +132,6 @@ public class RepoUpdater {
|
|||||||
downloader.setListener(downloadListener);
|
downloader.setListener(downloadListener);
|
||||||
downloader.download();
|
downloader.download();
|
||||||
|
|
||||||
if (downloader.isCached()) {
|
|
||||||
// The index is unchanged since we last read it. We just mark
|
|
||||||
// everything that came from this repo as being updated.
|
|
||||||
Utils.debugLog(TAG, "Repo index for " + indexUrl + " is up to date (by etag)");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (downloader != null && downloader.outputFile != null) {
|
if (downloader != null && downloader.outputFile != null) {
|
||||||
if (!downloader.outputFile.delete()) {
|
if (!downloader.outputFile.delete()) {
|
||||||
|
@ -84,14 +84,6 @@ public class BluetoothDownloader extends Downloader {
|
|||||||
connection.closeQuietly();
|
connection.closeQuietly();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCached() {
|
|
||||||
FileDetails details = getFileDetails();
|
|
||||||
return details != null &&
|
|
||||||
details.getCacheTag() != null &&
|
|
||||||
details.getCacheTag().equals(getCacheTag());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void close() {
|
protected void close() {
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
|
@ -75,18 +75,12 @@ public abstract class Downloader {
|
|||||||
this.cacheTag = cacheTag;
|
this.cacheTag = cacheTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean wantToCheckCache() {
|
|
||||||
return cacheTag != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean hasChanged();
|
public abstract boolean hasChanged();
|
||||||
|
|
||||||
protected abstract int totalDownloadSize();
|
protected abstract int totalDownloadSize();
|
||||||
|
|
||||||
public abstract void download() throws IOException, InterruptedException;
|
public abstract void download() throws IOException, InterruptedException;
|
||||||
|
|
||||||
public abstract boolean isCached();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return whether the requested file was not found in the repo (e.g. HTTP 404 Not Found)
|
* @return whether the requested file was not found in the repo (e.g. HTTP 404 Not Found)
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package org.fdroid.fdroid.net;
|
package org.fdroid.fdroid.net;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.fdroid.fdroid.BuildConfig;
|
import org.fdroid.fdroid.BuildConfig;
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
@ -17,18 +18,15 @@ import java.net.HttpURLConnection;
|
|||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import info.guardianproject.netcipher.NetCipher;
|
|
||||||
|
|
||||||
public class HttpDownloader extends Downloader {
|
public class HttpDownloader extends Downloader {
|
||||||
private static final String TAG = "HttpDownloader";
|
private static final String TAG = "HttpDownloader";
|
||||||
|
|
||||||
private static final String HEADER_IF_NONE_MATCH = "If-None-Match";
|
|
||||||
private static final String HEADER_FIELD_ETAG = "ETag";
|
private static final String HEADER_FIELD_ETAG = "ETag";
|
||||||
|
|
||||||
private final String username;
|
private final String username;
|
||||||
private final String password;
|
private final String password;
|
||||||
private HttpURLConnection connection;
|
private HttpURLConnection connection;
|
||||||
private int statusCode = -1;
|
private boolean newFileAvailableOnServer;
|
||||||
|
|
||||||
HttpDownloader(URL url, File destFile)
|
HttpDownloader(URL url, File destFile)
|
||||||
throws FileNotFoundException, MalformedURLException {
|
throws FileNotFoundException, MalformedURLException {
|
||||||
@ -70,24 +68,33 @@ public class HttpDownloader extends Downloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a remote file, checking the HTTP response code. If 'etag' is not
|
* Get a remote file, checking the HTTP response code and the {@code etag}.
|
||||||
* {@code null}, it's passed to the server as an If-None-Match header, in
|
* In order to prevent the {@code etag} from being used as a form of tracking
|
||||||
* which case expect a 304 response if nothing changed. In the event of a
|
* cookie, this code never sends the {@code etag} to the server. Instead, it
|
||||||
* 200 response ONLY, 'retag' (which should be passed empty) may contain
|
* uses a {@code HEAD} request to get the {@code etag} from the server, then
|
||||||
* an etag value for the response, or it may be left empty if none was
|
* only issues a {@code GET} if the {@code etag} has changed.
|
||||||
* available.
|
*
|
||||||
|
* @see <a href="http://lucb1e.com/rp/cookielesscookies">Cookieless cookies</a>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void download() throws IOException, InterruptedException {
|
public void download() throws IOException, InterruptedException {
|
||||||
// get the file size from the server
|
// get the file size from the server
|
||||||
HttpURLConnection tmpConn = getConnection();
|
HttpURLConnection tmpConn = getConnection();
|
||||||
tmpConn.setRequestMethod("HEAD");
|
tmpConn.setRequestMethod("HEAD");
|
||||||
|
String etag = tmpConn.getHeaderField(HEADER_FIELD_ETAG);
|
||||||
|
|
||||||
int contentLength = -1;
|
int contentLength = -1;
|
||||||
int statusCode = tmpConn.getResponseCode();
|
int statusCode = tmpConn.getResponseCode();
|
||||||
tmpConn.disconnect();
|
tmpConn.disconnect();
|
||||||
|
newFileAvailableOnServer = false;
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
contentLength = tmpConn.getContentLength();
|
contentLength = tmpConn.getContentLength();
|
||||||
|
if (!TextUtils.isEmpty(etag) && etag.equals(cacheTag)) {
|
||||||
|
Utils.debugLog(TAG, sourceUrl + " is cached, not downloading");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newFileAvailableOnServer = true;
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
notFound = true;
|
notFound = true;
|
||||||
@ -96,6 +103,7 @@ public class HttpDownloader extends Downloader {
|
|||||||
Utils.debugLog(TAG, "HEAD check of " + sourceUrl + " returned " + statusCode + ": "
|
Utils.debugLog(TAG, "HEAD check of " + sourceUrl + " returned " + statusCode + ": "
|
||||||
+ tmpConn.getResponseMessage());
|
+ tmpConn.getResponseMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean resumable = false;
|
boolean resumable = false;
|
||||||
long fileLength = outputFile.length();
|
long fileLength = outputFile.length();
|
||||||
if (fileLength > contentLength) {
|
if (fileLength > contentLength) {
|
||||||
@ -106,7 +114,9 @@ public class HttpDownloader extends Downloader {
|
|||||||
resumable = true;
|
resumable = true;
|
||||||
}
|
}
|
||||||
setupConnection(resumable);
|
setupConnection(resumable);
|
||||||
doDownload(resumable);
|
Utils.debugLog(TAG, "downloading " + sourceUrl + " (is resumable: " + resumable + ")");
|
||||||
|
downloadFromStream(8192, resumable);
|
||||||
|
cacheTag = connection.getHeaderField(HEADER_FIELD_ETAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSwapUrl() {
|
private boolean isSwapUrl() {
|
||||||
@ -147,37 +157,6 @@ public class HttpDownloader extends Downloader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doDownload(boolean resumable) throws IOException, InterruptedException {
|
|
||||||
if (wantToCheckCache()) {
|
|
||||||
setupCacheCheck();
|
|
||||||
Utils.debugLog(TAG, "Checking cached status of " + sourceUrl);
|
|
||||||
statusCode = connection.getResponseCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCached()) {
|
|
||||||
Utils.debugLog(TAG, sourceUrl + " is cached, so not downloading (HTTP " + statusCode + ")");
|
|
||||||
} else {
|
|
||||||
Utils.debugLog(TAG, "Need to download " + sourceUrl + " (is resumable: " + resumable + ")");
|
|
||||||
downloadFromStream(8192, resumable);
|
|
||||||
updateCacheCheck();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCached() {
|
|
||||||
return wantToCheckCache() && statusCode == 304;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupCacheCheck() {
|
|
||||||
if (cacheTag != null) {
|
|
||||||
connection.setRequestProperty(HEADER_IF_NONE_MATCH, cacheTag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCacheCheck() {
|
|
||||||
cacheTag = connection.getHeaderField(HEADER_FIELD_ETAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Testing in the emulator for me, showed that figuring out the
|
// Testing in the emulator for me, showed that figuring out the
|
||||||
// filesize took about 1 to 1.5 seconds.
|
// filesize took about 1 to 1.5 seconds.
|
||||||
// To put this in context, downloading a repo of:
|
// To put this in context, downloading a repo of:
|
||||||
@ -193,7 +172,7 @@ public class HttpDownloader extends Downloader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasChanged() {
|
public boolean hasChanged() {
|
||||||
return this.statusCode != 304;
|
return newFileAvailableOnServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,9 +49,4 @@ public class LocalFileDownloader extends Downloader {
|
|||||||
notFound = true;
|
notFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCached() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user