Skip to content

Inspecting HttpResponse content in BackOffRequired results in IOException later #1403

@pingw33n

Description

@pingw33n

When implementing retries for Compute client one needs to read and parse HttpResponse as JSON in order to find rateLimitExceeded error in details (we could rely on the status code but unfortunately it's a generic 403 Forbidden in this case). Later when the library attempts to read the response again to throw GoogleJsonResponseException it won't be able to fill details field because the HTTP content has been already read (it also printStackTraces an IOException) .

private HttpBackOffUnsuccessfulResponseHandler createRetryHandler() {
            BackOff backOff = new ExponentialBackOff.Builder()
                .setInitialIntervalMillis(1000)
                .setMaxIntervalMillis(5000)
                .setMaxElapsedTimeMillis(60_000)
                .build();
            HttpBackOffUnsuccessfulResponseHandler retryHandler = new HttpBackOffUnsuccessfulResponseHandler(backOff) {
                @Override
                public boolean handleResponse(HttpRequest request, HttpResponse response, boolean supportsRetry)
                    throws IOException {

                    return httpCredentialsAdapter.handleResponse(request, response, supportsRetry) ||
                        super.handleResponse(request, response, supportsRetry);
                }
            };
            retryHandler.setBackOffRequired(resp -> {
                GoogleJsonResponseException exc = GoogleJsonResponseException.from(JacksonFactory.getDefaultInstance(),
                                                                                   resp);
                return
                    exc.getDetails().getErrors().stream().anyMatch(err -> "rateLimitExceeded".equals(err.getReason()));
            });
            return retryHandler;
        }
java.io.IOException: Stream closed
	at java.base/java.util.zip.GZIPInputStream.ensureOpen(GZIPInputStream.java:63)
	at java.base/java.util.zip.GZIPInputStream.read(GZIPInputStream.java:114)
	at org.apache.http.client.entity.LazyDecompressingInputStream.read(LazyDecompressingInputStream.java:70)
	at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(ByteSourceJsonBootstrapper.java:539)
	at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.detectEncoding(ByteSourceJsonBootstrapper.java:133)
	at com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.constructParser(ByteSourceJsonBootstrapper.java:256)
	at com.fasterxml.jackson.core.JsonFactory._createParser(JsonFactory.java:1656)
	at com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:1085)
	at com.fasterxml.jackson.core.JsonFactory.createJsonParser(JsonFactory.java:1466)
	at com.google.api.client.json.jackson2.JacksonFactory.createJsonParser(JacksonFactory.java:85)
	at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:102)
	at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:118)
	at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:37)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:428)
	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1108)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:514)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:455)
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:565)

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions