Skip to content

Commit

Permalink
Merge branch 'master' into retrying-client
Browse files Browse the repository at this point in the history
Conflicts:
	src/main/java/io/tus/java/client/TusClient.java
  • Loading branch information
Acconut committed May 12, 2016
2 parents af06d68 + ff319ed commit 893678f
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 29 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ The JARs can be downloaded manually from our [Bintray project](https://bintray.c
**Gradle:**

```groovy
compile 'io.tus.java.client:tus-java-client:0.1.4'
compile 'io.tus.java.client:tus-java-client:0.2.1'
```

**Maven:**
Expand Down
8 changes: 6 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
apply plugin: 'java'
apply plugin: 'maven'

group 'io.tus.java.client'

repositories {
mavenCentral()
allprojects {
repositories {
mavenCentral()
}
}

dependencies {
compile 'org.jetbrains:annotations:13.0'
testCompile 'junit:junit:4.12'
testCompile 'org.mock-server:mockserver-netty:3.9.17'
}
Expand Down
2 changes: 1 addition & 1 deletion example/src/main/java/io/tus/java/example/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static void main(String[] args) {

// Configure tus HTTP endpoint. This URL will be used for creating new uploads
// using the Creation extension
client.setUploadCreationURL(new URL("http://localhost:1080/files/"));
client.setUploadCreationURL(new URL("http://master.tus.io/files/"));

// Enable resumable uploads by storing the upload URL in memory
client.enableResuming(new TusURLMemoryStore());
Expand Down
53 changes: 46 additions & 7 deletions src/main/java/io/tus/java/client/TusClient.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package io.tus.java.client;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

/**
* This class is used for creating or resuming uploads.
Expand All @@ -18,6 +22,7 @@ public class TusClient {
private URL uploadCreationURL;
private boolean resumingEnabled;
private TusURLStore urlStore;
private Map<String, String> headers;

/**
* Create a new tus client.
Expand Down Expand Up @@ -52,7 +57,7 @@ public URL getUploadCreationURL() {
*
* @param urlStore Storage used to save and retrieve upload URLs by its fingerprint.
*/
public void enableResuming(TusURLStore urlStore) {
public void enableResuming(@NotNull TusURLStore urlStore) {
resumingEnabled = true;
this.urlStore = urlStore;
}
Expand All @@ -79,6 +84,34 @@ public boolean resumingEnabled() {
return resumingEnabled;
}

/**
* Set headers which will be added to every HTTP requestes made by this TusClient instance.
* These may to overwrite tus-specific headers, which can be identified by their Tus-*
* prefix, and can cause unexpected behavior.
*
* @see #getHeaders()
* @see #prepareConnection(URLConnection)
*
* @param headers The map of HTTP headers
*/
public void setHeaders(@Nullable Map<String, String> headers) {
this.headers = headers;
}

/**
* Get the HTTP headers which should be contained in every request and were configured using
* {@link #setHeaders(Map)}.
*
* @see #setHeaders(Map)
* @see #prepareConnection(URLConnection)
*
* @return The map of configured HTTP headers
*/
@Nullable
public Map<String, String> getHeaders() {
return headers;
}

/**
* Create a new upload using the Creation extension. Before calling this function, an "upload
* creation URL" must be defined using {@link #setUploadCreationURL(URL)} or else this
Expand All @@ -92,7 +125,7 @@ public boolean resumingEnabled() {
* wrong status codes or missing/invalid headers.
* @throws IOException Thrown if an exception occurs while issuing the HTTP request.
*/
public TusUploader createUpload(TusUpload upload) throws ProtocolException, IOException {
public TusUploader createUpload(@NotNull TusUpload upload) throws ProtocolException, IOException {
HttpURLConnection connection = (HttpURLConnection) uploadCreationURL.openConnection();
connection.setRequestMethod("POST");
prepareConnection(connection);
Expand Down Expand Up @@ -141,7 +174,7 @@ public TusUploader createUpload(TusUpload upload) throws ProtocolException, IOEx
* wrong status codes or missing/invalid headers.
* @throws IOException Thrown if an exception occurs while issuing the HTTP request.
*/
public TusUploader resumeUpload(TusUpload upload) throws FingerprintNotFoundException, ResumingNotEnabledException, ProtocolException, IOException {
public TusUploader resumeUpload(@NotNull TusUpload upload) throws FingerprintNotFoundException, ResumingNotEnabledException, ProtocolException, IOException {
if(!resumingEnabled) {
throw new ResumingNotEnabledException();
}
Expand Down Expand Up @@ -181,7 +214,7 @@ public TusUploader resumeUpload(TusUpload upload) throws FingerprintNotFoundExce
* wrong status codes or missing/invalid headers.
* @throws IOException Thrown if an exception occurs while issuing the HTTP request.
*/
public TusUploader resumeOrCreateUpload(TusUpload upload) throws ProtocolException, IOException {
public TusUploader resumeOrCreateUpload(@NotNull TusUpload upload) throws ProtocolException, IOException {
try {
return resumeUpload(upload);
} catch(FingerprintNotFoundException e) {
Expand All @@ -192,12 +225,18 @@ public TusUploader resumeOrCreateUpload(TusUpload upload) throws ProtocolExcepti
}

/**
* Set headers used for every HTTP request. Currently, this will add the Tus-Resumable header.
* Set headers used for every HTTP request. Currently, this will add the Tus-Resumable header
* and any custom header which can be configured using {@link #setHeaders(Map)},
*
* @param connection The connection whose headers will be modified.
*/
public void prepareConnection(URLConnection connection) {
public void prepareConnection(@NotNull URLConnection connection) {
connection.addRequestProperty("Tus-Resumable", TUS_VERSION);
// TODO: add custom headers

if(headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
connection.addRequestProperty(entry.getKey(), entry.getValue());
}
}
}
}
10 changes: 8 additions & 2 deletions src/main/java/io/tus/java/client/TusUpload.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package io.tus.java.client;

import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
Expand Down Expand Up @@ -31,11 +34,14 @@ public TusUpload() {
* @param file The file whose content should be later uploaded.
* @throws FileNotFoundException Thrown if the file cannot be found.
*/
public TusUpload(File file) throws FileNotFoundException {
public TusUpload(@NotNull File file) throws FileNotFoundException {
size = file.length();
input = new FileInputStream(file);

fingerprint = String.format("%s-%d", file.getAbsolutePath(), size);

metadata = new HashMap<String, String>();
metadata.put("filename", file.getName());
}

public long getSize() {
Expand Down Expand Up @@ -111,7 +117,7 @@ public String getEncodedMetadata() {
* published on Wikipedia (https://en.wikipedia.org/wiki/Base64#Sample_Implementation_in_Java)
* under the Creative Commons Attribution-ShareAlike License.
*/
private static String base64Encode(byte[] in) {
static String base64Encode(byte[] in) {
StringBuilder out = new StringBuilder((in.length * 4) / 3);
String codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

Expand Down
21 changes: 16 additions & 5 deletions src/main/java/io/tus/java/client/TusUploader.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
* <br>
* After obtaining an instance you can upload a file by following these steps:
* <ol>
* <li>Upload a chunk using {@link #uploadChunk(int)}</li>
* <li>Upload a chunk using {@link #uploadChunk()}</li>
* <li>Optionally get the new offset ({@link #getOffset()} to calculate the progress</li>
* <li>Repeat step 1 until the {@link #uploadChunk(int)} returns -1</li>
* <li>Repeat step 1 until the {@link #uploadChunk()} returns -1</li>
* <li>Close HTTP connection and InputStream using {@link #finish()} to free resources</li>
* </ol>
*/
Expand All @@ -40,7 +40,7 @@ public class TusUploader {
* @param offset Offset to read from
* @throws IOException Thrown if an exception occurs while issuing the HTTP request.
*/
public TusUploader(TusClient client, URL uploadURL, InputStream input, long offset) throws IOException {
public TusUploader(TusClient client, URL uploadURL, InputStream input, long offset) throws IOException, io.tus.java.client.ProtocolException {
this.uploadURL = uploadURL;
this.input = input;
this.offset = offset;
Expand All @@ -53,6 +53,7 @@ public TusUploader(TusClient client, URL uploadURL, InputStream input, long offs
client.prepareConnection(connection);
connection.setRequestProperty("Upload-Offset", Long.toString(offset));
connection.setRequestProperty("Content-Type", "application/offset+octet-stream");
connection.setRequestProperty("Expect", "100-continue");
try {
connection.setRequestMethod("PATCH");
// Check whether we are running on a buggy JRE
Expand All @@ -63,7 +64,17 @@ public TusUploader(TusClient client, URL uploadURL, InputStream input, long offs

connection.setDoOutput(true);
connection.setChunkedStreamingMode(0);
output = connection.getOutputStream();
try {
output = connection.getOutputStream();
} catch(ProtocolException pe) {
// If we already have a response code available, our expectation using the "Expect: 100-
// continue" header failed and we should handle this response.
if(connection.getResponseCode() != -1) {
finish();
}

throw pe;
}
}

/**
Expand Down Expand Up @@ -187,7 +198,7 @@ public URL getUploadURL() {
*/
public void finish() throws io.tus.java.client.ProtocolException, IOException {
input.close();
output.close();
if(output != null) output.close();
int responseCode = connection.getResponseCode();
connection.disconnect();

Expand Down
21 changes: 21 additions & 0 deletions src/test/java/io/tus/java/client/TestTusClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

Expand Down Expand Up @@ -206,4 +207,24 @@ public void testPrepareConnection() throws IOException {

assertEquals(connection.getRequestProperty("Tus-Resumable"), TusClient.TUS_VERSION);
}

@Test
public void testSetHeaders() throws IOException {
HttpURLConnection connection = (HttpURLConnection) mockServerURL.openConnection();
TusClient client = new TusClient();

Map<String, String> headers = new HashMap<String, String>();
headers.put("Greeting", "Hello");
headers.put("Important", "yes");
headers.put("Tus-Resumable", "evil");

assertNull(client.getHeaders());
client.setHeaders(headers);
assertEquals(headers, client.getHeaders());

client.prepareConnection(connection);

assertEquals(connection.getRequestProperty("Greeting"), "Hello");
assertEquals(connection.getRequestProperty("Important"), "yes");
}
}
14 changes: 10 additions & 4 deletions src/test/java/io/tus/java/client/TestTusUpload.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
public class TestTusUpload extends TestCase {
public void testTusUploadFile() throws IOException {
String content = "hello world";
Map<String, String> metadata = new LinkedHashMap<String, String>();
metadata.put("foo", "hello");
metadata.put("bar", "world");

File file = File.createTempFile("tus-upload-test", ".tmp");
OutputStream output = new FileOutputStream(file);
Expand All @@ -23,9 +20,18 @@ public void testTusUploadFile() throws IOException {

TusUpload upload = new TusUpload(file);

Map<String, String> metadata = new LinkedHashMap<String, String>();
metadata.put("foo", "hello");
metadata.put("bar", "world");
metadata.putAll(upload.getMetadata());

assertEquals(metadata.get("filename"), file.getName());

upload.setMetadata(metadata);
assertEquals(upload.getMetadata(), metadata);
assertEquals(upload.getEncodedMetadata(), "foo aGVsbG8=,bar d29ybGQ=");
assertEquals(
upload.getEncodedMetadata(),
"foo aGVsbG8=,bar d29ybGQ=,filename " + TusUpload.base64Encode(file.getName().getBytes()));

assertEquals(upload.getSize(), content.length());
assertNotSame(upload.getFingerprint(), "");
Expand Down
Loading

0 comments on commit 893678f

Please sign in to comment.