Merge pull request #8414 from tidoemanuele:tidoemanuele-improve-non-2xx-message

PiperOrigin-RevId: 350797551
This commit is contained in:
Oliver Woodman 2021-01-08 19:09:15 +00:00
commit 953e4e89e2
4 changed files with 55 additions and 20 deletions

View file

@ -550,19 +550,11 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
UrlResponseInfo responseInfo = Assertions.checkNotNull(this.responseInfo);
int responseCode = responseInfo.getHttpStatusCode();
if (responseCode < 200 || responseCode > 299) {
byte[] responseBody = Util.EMPTY_BYTE_ARRAY;
ByteBuffer readBuffer = getOrCreateReadBuffer();
while (!readBuffer.hasRemaining()) {
operation.close();
readBuffer.clear();
readInternal(readBuffer);
if (finished) {
break;
}
readBuffer.flip();
int existingResponseBodyEnd = responseBody.length;
responseBody = Arrays.copyOf(responseBody, responseBody.length + readBuffer.remaining());
readBuffer.get(responseBody, existingResponseBodyEnd, readBuffer.remaining());
byte[] responseBody;
try {
responseBody = readResponseBody();
} catch (HttpDataSourceException e) {
responseBody = Util.EMPTY_BYTE_ARRAY;
}
InvalidResponseCodeException exception =
@ -859,6 +851,29 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
currentConnectTimeoutMs = clock.elapsedRealtime() + connectTimeoutMs;
}
/**
* Reads the whole response body.
*
* @return The response body.
* @throws HttpDataSourceException If an error occurs reading from the source.
*/
private byte[] readResponseBody() throws HttpDataSourceException {
byte[] responseBody = Util.EMPTY_BYTE_ARRAY;
ByteBuffer readBuffer = getOrCreateReadBuffer();
while (!finished) {
operation.close();
readBuffer.clear();
readInternal(readBuffer);
readBuffer.flip();
if (readBuffer.remaining() > 0) {
int existingResponseBodyEnd = responseBody.length;
responseBody = Arrays.copyOf(responseBody, responseBody.length + readBuffer.remaining());
readBuffer.get(responseBody, existingResponseBodyEnd, readBuffer.remaining());
}
}
return responseBody;
}
/**
* Reads up to {@code buffer.remaining()} bytes of data from {@code currentUrlRequest} and stores
* them into {@code buffer}. If there is an error and {@code buffer == readBuffer}, then it resets

View file

@ -41,6 +41,7 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException;
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
@ -380,7 +381,8 @@ public final class CronetDataSourceTest {
}
@Test
public void requestOpenPropagatesFailureResponseBody() throws Exception {
public void requestOpen_withNon2xxResponseCode_throwsInvalidResponseCodeExceptionWithBody()
throws Exception {
mockResponseStartSuccess();
// Use a size larger than CronetDataSource.READ_BUFFER_SIZE_BYTES
int responseLength = 40 * 1024;
@ -389,8 +391,8 @@ public final class CronetDataSourceTest {
try {
dataSourceUnderTest.open(testDataSpec);
fail("HttpDataSource.InvalidResponseCodeException expected");
} catch (HttpDataSource.InvalidResponseCodeException e) {
fail("InvalidResponseCodeException expected");
} catch (InvalidResponseCodeException e) {
assertThat(e.responseBody).isEqualTo(buildTestDataArray(0, responseLength));
// Check for connection not automatically closed.
verify(mockUrlRequest, never()).cancel();
@ -399,6 +401,26 @@ public final class CronetDataSourceTest {
}
}
@Test
public void
requestOpen_withNon2xxResponseCode_andRequestBodyReadFailure_throwsInvalidResponseCodeExceptionWithoutBody()
throws Exception {
mockResponseStartSuccess();
mockReadFailure();
testUrlResponseInfo = createUrlResponseInfo(/* statusCode= */ 500);
try {
dataSourceUnderTest.open(testDataSpec);
fail("InvalidResponseCodeException expected");
} catch (InvalidResponseCodeException e) {
assertThat(e.responseBody).isEmpty();
// Check for connection not automatically closed.
verify(mockUrlRequest, never()).cancel();
verify(mockTransferListener, never())
.onTransferStart(dataSourceUnderTest, testDataSpec, /* isNetwork= */ true);
}
}
@Test
public void requestOpenValidatesContentTypePredicate() {
mockResponseStartSuccess();

View file

@ -308,8 +308,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
try {
errorResponseBody = Util.toByteArray(Assertions.checkNotNull(responseByteStream));
} catch (IOException e) {
throw new HttpDataSourceException(
"Error reading non-2xx response body", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
errorResponseBody = Util.EMPTY_BYTE_ARRAY;
}
Map<String, List<String>> headers = response.headers().toMultimap();
closeConnectionQuietly();

View file

@ -377,8 +377,7 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
errorResponseBody =
errorStream != null ? Util.toByteArray(errorStream) : Util.EMPTY_BYTE_ARRAY;
} catch (IOException e) {
throw new HttpDataSourceException(
"Error reading non-2xx response body", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
errorResponseBody = Util.EMPTY_BYTE_ARRAY;
}
closeConnectionQuietly();
InvalidResponseCodeException exception =