Skip to content

Commit

Permalink
Properly close ResponseBody when closing the InputStream
Browse files Browse the repository at this point in the history
ResponseBody objects from Okhttp needs to be closed and, right now, we
just close the InputStream which is not sufficient.

I noticed that because I saw some warnings about leaked ResponseBody
instances in my logs.
  • Loading branch information
gsmet committed Nov 29, 2020
1 parent ed4f9c8 commit f5ad332
Showing 1 changed file with 70 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
Expand Down Expand Up @@ -179,7 +180,7 @@ HttpURLConnection open(URL url, @Nullable Proxy proxy) {
* <p>
* This code configures OkHttp to handle all HTTP and HTTPS connections created with
* {@link java.net.URL#openConnection()}:
*
*
* <pre>
* {
* &#64;code
Expand Down Expand Up @@ -404,7 +405,7 @@ public InputStream getErrorStream() {
try {
Response response = getResponse(true);
if (hasBody(response) && response.code() >= HTTP_BAD_REQUEST) {
return response.body().byteStream();
return new ResponseBodyInputStream(response.body());
}
return null;
} catch (IOException e) {
Expand Down Expand Up @@ -486,7 +487,7 @@ public InputStream getInputStream() throws IOException {
Response response = getResponse(false);
if (response.code() >= HTTP_BAD_REQUEST)
throw new FileNotFoundException(url.toString());
return response.body().byteStream();
return new ResponseBodyInputStream(response.body());
}

@Override
Expand Down Expand Up @@ -957,6 +958,7 @@ static final class StreamedRequestBody extends OutputStreamRequestBody {
initOutputStream(Okio.buffer(pipe.sink()), expectedContentLength);
}

@Override
public boolean isOneShot() {
return true;
}
Expand Down Expand Up @@ -1367,4 +1369,69 @@ static final class UnexpectedException extends IOException {
super(cause);
}
}

/**
* Make sure both the ResponseBody and the InputStream are closed when the InputStream coming from the ResponseBody
* is closed.
*/
private static final class ResponseBodyInputStream extends InputStream {

private final ResponseBody responseBody;

private final InputStream inputStream;

private ResponseBodyInputStream(ResponseBody responseBody) {
this.responseBody = responseBody;
this.inputStream = responseBody.byteStream();
}

@Override
public int read() throws IOException {
return inputStream.read();
}

@Override
public int read(byte b[]) throws IOException {
return inputStream.read(b);
}

@Override
public int read(byte b[], int off, int len) throws IOException {
return inputStream.read(b, off, len);
}

@Override
public long skip(long n) throws IOException {
return inputStream.skip(n);
}

@Override
public int available() throws IOException {
return inputStream.available();
}

@Override
public synchronized void mark(int readlimit) {
inputStream.mark(readlimit);
}

@Override
public synchronized void reset() throws IOException {
inputStream.reset();
}

@Override
public boolean markSupported() {
return inputStream.markSupported();
}

@Override
public void close() throws IOException {
try {
inputStream.close();
} finally {
responseBody.close();
}
}
}
}

0 comments on commit f5ad332

Please sign in to comment.