Skip to content

Commit 9b4bb82

Browse files
authored
fix: improve 503 handling for json resumable uploads (#2289)
1 parent cc65fd0 commit 9b4bb82

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/JsonResumableSessionPutTask.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,17 @@ public void rewindTo(long offset) {
190190
} else {
191191
HttpResponseException cause = new HttpResponseException(response);
192192
String contentType = response.getHeaders().getContentType();
193+
Long contentLength = response.getHeaders().getContentLength();
193194
// If the content-range header value has run ahead of the backend, it will respond with
194195
// a 503 with plain text content
195196
// Attempt to detect this very loosely as to minimize impact of modified error message
196197
// This is accurate circa 2023-06
197198
if ((!JsonResumableSessionFailureScenario.isOk(code)
198199
&& !JsonResumableSessionFailureScenario.isContinue(code))
199200
&& contentType != null
200-
&& contentType.startsWith("text/plain")) {
201+
&& contentType.startsWith("text/plain")
202+
&& contentLength != null
203+
&& contentLength > 0) {
201204
String errorMessage = cause.getContent().toLowerCase(Locale.US);
202205
if (errorMessage.contains("content-range")) {
203206
StorageException se =

google-cloud-storage/src/test/java/com/google/cloud/storage/ITJsonResumableSessionPutTaskTest.java

+31
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,37 @@ public void scenario5() throws Exception {
740740
}
741741
}
742742

743+
@Test
744+
public void _503_emptyBody() throws Exception {
745+
HttpRequestHandler handler =
746+
req -> {
747+
FullHttpResponse resp =
748+
new DefaultFullHttpResponse(req.protocolVersion(), APPEND_GREATER_THAN_CURRENT_SIZE);
749+
resp.headers().set(CONTENT_TYPE, "text/plain; charset=utf-8");
750+
return resp;
751+
};
752+
753+
try (FakeHttpServer fakeHttpServer = FakeHttpServer.of(handler);
754+
TmpFile tmpFile =
755+
DataGenerator.base64Characters().tempFile(temp.newFolder().toPath(), _256KiBL)) {
756+
URI endpoint = fakeHttpServer.getEndpoint();
757+
String uploadUrl = String.format("%s/upload/%s", endpoint.toString(), UUID.randomUUID());
758+
759+
AtomicLong confirmedBytes = new AtomicLong(-1L);
760+
761+
JsonResumableSessionPutTask task =
762+
new JsonResumableSessionPutTask(
763+
httpClientContext,
764+
uploadUrl,
765+
RewindableContent.of(tmpFile.getPath()),
766+
HttpContentRange.of(ByteRangeSpec.explicit(_512KiBL, _768KiBL)));
767+
768+
StorageException se = assertThrows(StorageException.class, task::call);
769+
assertThat(se.getCode()).isEqualTo(503);
770+
assertThat(confirmedBytes.get()).isEqualTo(-1);
771+
}
772+
}
773+
743774
@Test
744775
public void jsonParseFailure() throws Exception {
745776

0 commit comments

Comments
 (0)