Skip to content

Commit f1400fc

Browse files
committed
Add API2 upload body headers proof
1 parent ca49fb1 commit f1400fc

3 files changed

Lines changed: 165 additions & 0 deletions

File tree

example/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ tasks.register('api2DevdockTusRequestLifecycleHooks', JavaExec) {
3030
workingDir = rootProject.projectDir
3131
}
3232

33+
tasks.register('api2DevdockTusUploadBodyHeaders', JavaExec) {
34+
classpath = sourceSets.main.runtimeClasspath
35+
mainClass = 'io.tus.java.example.Api2DevdockTusUploadBodyHeaders'
36+
workingDir = rootProject.projectDir
37+
}
38+
3339
tasks.register('api2DevdockTusCustomRequestHeaders', JavaExec) {
3440
classpath = sourceSets.main.runtimeClasspath
3541
mainClass = 'io.tus.java.example.Api2DevdockTusCustomRequestHeaders'

example/src/main/java/io/tus/java/example/Api2DevdockScenario.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ static Map<String, String> uploadHeaders(JSONObject uploadConfig) {
139139
return stringMap(uploadConfig.getJSONObject("headers"));
140140
}
141141

142+
static Map<String, Map<String, String>> uploadBodyHeadersByMethod(JSONObject uploadConfig) {
143+
final JSONObject bodyHeadersByMethod = uploadConfig.getJSONObject("bodyHeadersByMethod");
144+
final Map<String, Map<String, String>> result =
145+
new LinkedHashMap<String, Map<String, String>>();
146+
for (String method : bodyHeadersByMethod.keySet()) {
147+
result.put(method, stringMap(bodyHeadersByMethod.getJSONObject(method)));
148+
}
149+
150+
return result;
151+
}
152+
142153
static boolean uploadAddRequestId(JSONObject uploadConfig) {
143154
return uploadConfig.getBoolean("addRequestId");
144155
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package io.tus.java.example;
2+
3+
import io.tus.java.client.ProtocolException;
4+
import io.tus.java.client.TusClient;
5+
import io.tus.java.client.TusRequestLifecycleHooks;
6+
import io.tus.java.client.TusURLMemoryStore;
7+
import io.tus.java.client.TusUpload;
8+
import io.tus.java.client.TusUploader;
9+
import org.json.JSONObject;
10+
11+
import java.io.ByteArrayInputStream;
12+
import java.io.IOException;
13+
import java.net.HttpURLConnection;
14+
import java.net.URL;
15+
import java.util.LinkedHashMap;
16+
import java.util.Map;
17+
18+
public final class Api2DevdockTusUploadBodyHeaders {
19+
/**
20+
* Run the API2 devdock TUS upload body headers example.
21+
*
22+
* @param args ignored
23+
*/
24+
public static void main(String[] args) {
25+
try {
26+
System.setProperty("http.strictPostRedirect", "true");
27+
28+
final JSONObject scenario = Api2DevdockScenario.loadScenario();
29+
final JSONObject createResponse = Api2DevdockScenario.createResponse(scenario);
30+
final JSONObject result = uploadWithBodyHeaders(scenario, createResponse);
31+
Api2DevdockScenario.writeResult(result);
32+
33+
System.out.println(
34+
"Java TUS SDK devdock scenario "
35+
+ scenario.getString("scenarioId")
36+
+ " observed upload body headers for "
37+
+ result.getString("uploadUrl")
38+
);
39+
} catch (Exception e) {
40+
e.printStackTrace();
41+
System.exit(1);
42+
}
43+
}
44+
45+
private static JSONObject uploadWithBodyHeaders(
46+
JSONObject scenario,
47+
JSONObject createResponse
48+
) throws IOException, ProtocolException {
49+
final JSONObject uploadConfig = scenario.getJSONObject("upload");
50+
final byte[] content = Api2DevdockScenario.scenarioBytes(uploadConfig);
51+
final Map<String, Map<String, String>> expectedHeadersByMethod =
52+
Api2DevdockScenario.uploadBodyHeadersByMethod(uploadConfig);
53+
final Map<String, Map<String, String>> bodyHeadersByMethod =
54+
new LinkedHashMap<String, Map<String, String>>();
55+
Api2DevdockScenario.requireFullFileChunkSize(uploadConfig);
56+
57+
final TusClient client = new TusClient();
58+
client.setUploadCreationURL(
59+
new URL(Api2DevdockScenario.tusUrl(uploadConfig, scenario, createResponse))
60+
);
61+
client.enableResuming(new TusURLMemoryStore());
62+
client.setRequestLifecycleHooks(new TusRequestLifecycleHooks(
63+
new TusRequestLifecycleHooks.BeforeRequest() {
64+
@Override
65+
public void beforeRequest(TusRequestLifecycleHooks.RequestContext context) {
66+
final Map<String, String> expectedHeaders =
67+
expectedHeadersByMethod.get(context.getMethod());
68+
if (expectedHeaders == null) {
69+
return;
70+
}
71+
72+
bodyHeadersByMethod.put(
73+
context.getMethod(),
74+
observedBodyHeaders(
75+
context.getConnection(),
76+
context.getMethod(),
77+
expectedHeaders
78+
)
79+
);
80+
}
81+
},
82+
null
83+
));
84+
85+
final TusUpload upload = new TusUpload();
86+
upload.setInputStream(new ByteArrayInputStream(content));
87+
upload.setSize(content.length);
88+
upload.setFingerprint(scenario.getString("scenarioId") + "-java-upload-body-headers");
89+
upload.setMetadata(
90+
Api2DevdockScenario.uploadMetadata(uploadConfig, scenario, createResponse)
91+
);
92+
93+
final TusUploader uploader = client.resumeOrCreateUpload(upload);
94+
uploader.setChunkSize(content.length);
95+
int uploadedChunkSize;
96+
do {
97+
uploadedChunkSize = uploader.uploadChunk();
98+
} while (uploadedChunkSize > -1);
99+
uploader.finish();
100+
101+
if (uploader.getOffset() != content.length) {
102+
throw new IllegalStateException(
103+
"upload body headers upload offset "
104+
+ uploader.getOffset()
105+
+ ", expected "
106+
+ content.length
107+
);
108+
}
109+
if (uploader.getUploadURL() == null) {
110+
throw new IllegalStateException("upload body headers upload did not expose a URL");
111+
}
112+
for (String method : expectedHeadersByMethod.keySet()) {
113+
if (!bodyHeadersByMethod.containsKey(method)) {
114+
throw new IllegalStateException(
115+
"upload body headers did not observe " + method + " request"
116+
);
117+
}
118+
}
119+
120+
return new JSONObject()
121+
.put("bodyHeadersByMethod", new JSONObject(bodyHeadersByMethod))
122+
.put("uploadUrl", uploader.getUploadURL().toString());
123+
}
124+
125+
private static Map<String, String> observedBodyHeaders(
126+
HttpURLConnection connection,
127+
String method,
128+
Map<String, String> expectedHeaders
129+
) {
130+
final Map<String, String> headers = new LinkedHashMap<String, String>();
131+
for (Map.Entry<String, String> entry : expectedHeaders.entrySet()) {
132+
final String value = connection.getRequestProperty(entry.getKey());
133+
if (value == null) {
134+
throw new IllegalStateException(
135+
"upload body headers did not observe " + entry.getKey() + " on " + method
136+
);
137+
}
138+
139+
headers.put(entry.getKey(), value);
140+
}
141+
142+
return headers;
143+
}
144+
145+
private Api2DevdockTusUploadBodyHeaders() {
146+
throw new IllegalStateException("Utility class");
147+
}
148+
}

0 commit comments

Comments
 (0)