The error occurs when OkHttp try to reuse a connection that is in FIN_WAIT2 state in server, because the server keep_alive timeout is lesser than the client timeout.
StackTrace:
Exception in thread "main" java.io.IOException: unexpected end of stream on okhttp3.Address@e06a4fc7
at okhttp3.internal.http.Http1xStream.readResponse(Http1xStream.java:201)
at okhttp3.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:127)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:53)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:124)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.execute(RealCall.java:60)
at br.com.edallagnol.test.App.main(App.java:54)
Caused by: java.io.EOFException: \n not found: size=0 content=…
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:215)
at okhttp3.internal.http.Http1xStream.readResponse(Http1xStream.java:186)
... 17 more
Steps to reproduce:
-Configure a Tomcat(7 or 8) Server with a keep_alive timeout of 60 seconds (default);
-Create a OkHttpClient with retryOnConnectionFailure(false) and the default ConnectionPool (5 min timeout);
-Do a GET request with client.newCall(request).execute();
-Wait more than 60 seconds (or monitor the connection state, until FIN_WAIT2 state);
-Do a GET request with client.newCall(request).execute(), using the same client;
Sample code:
OkHttpClient client = new OkHttpClient.Builder()
.retryOnConnectionFailure(false)
.build();
for (int i=0; i != 10; i++) {
Response response = client.newCall(new Request.Builder()
.url("http://localhost:8080/")
.get()
.build()).execute();
try {
System.out.println(response.body().string());
} finally {
response.close();
}
Thread.sleep(61000);
}
*OkHttp version 3.4.1.
Here's your fix:
OkHttpClient client = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.build();
I know, but it's not a bug in OkHttp? Should not it send back a FIN and ACK to the server, and start a new connection, instead of reusing this one?
As far as I can tell, there’s no efficient way to detect that the connection has been closed. If you can find one, we’d love to use it!
Thanks for response.
Closing this issue.
addHeader("Connection","close")? can solve this problem? same as call retryOnConnectionFailure(true)??
please give a reply ,thanks
response header ("Connection":"close") solved this issue in my case
Hi, somehow this is problem with URL. I am trying with another URL, it is working fine for me.
i am using version 2.3.0 & ok http 3.2.0
i am also facing the same problem, getting error response on AndroidNetworking.post(); method, please help me to solve this...
Response is: com.androidnetworking.error.ANError: java.io.IOException: unexpected end of stream on okhttp3.Address@93136865
In my case, it`s been server-side error, not client.
Just wrote backend-guys about it and was waiting for a fixes:)
It is strange but this kind of exception is thrown also when running the application on the android emulator. I have a virtual machine ubuntu where my server runs, and I have defined as a bridge adapter so I can connect to the server via my local computer where the virtual machine runs on. So on my computer (windows 10 os) I am running the android studio with the emulator where I connect to the server via okhttp client with post method to send some data. When I got the response back which is large I try to convert it to jsonarray and then parse the array to finally get the wanted results and then to display them. But it is strange that sometimes the exception is fired on and sometimes not even for the same request post I am sending which means for the same response I am waiting for.
I really do not know how to fix this.
This is on my Flask server (on my virtual machine ) which is running:
response = Response(
json.dumps(recommended_products),
status=200,
mimetype='application/json'
)
And in the async task on Android :
@Override
protected String doInBackground(Void... voids) {
try {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
return null;
}
ResponseBody responseBody = response.body();
if(responseBody != null && responseBody.contentLength() > 0) {
InputStream is = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String result="";
String line;
while((line = reader.readLine()) != null) { //here I got the exception sometimes
result += line;
}
response.body().close();
JSONArray results = new JSONArray(result);
for(int i = 0; i < results.length(); i++) {
JSONArray obj = results.getJSONArray(i);
String name = obj.toString();
mes_res.add(name);
}
return result;
}
else
return "null";
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I can't fix this.
@swankjesse How can the calling application recover from this if it is not using retryOnConnectionFailure(cause in some cases we can not use retryOnConenctionFailure) ?
evictAll in Connection Pool ? What is your suggestion?
We keep getting this exception . Shouldn't the connection be automatically closed after this exception ?
Caused by: java.io.IOException: unexpected end of stream on Connection
at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:205)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:75)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:211)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
at okhttp3.RealCall.execute(RealCall.java:69)
@pc9292 please create a new issue with a standalone executable test case.
I am getting unexpected end of stream on connection issue please help me to fix this.
Ohhh.... guys, I can't understand why I faced with the same issue, no one of workaround doesn't help me
My stack trace:
java.io.IOException: unexpected end of stream on http://localhost:8080/...
at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.java:236)
at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.java:115)
at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:94)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:43)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:88)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at com.here.platform.cm.BaseApiTests.lambda$getCMApiClient$0(BaseApiTests.java:27)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:223)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:221)
at okhttp3.RealCall.execute(RealCall.java:81)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
at com.here.platform.cm.CreateConsentRequestTests.createConsentRequestTest(CreateConsentRequestTests.java:36)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:628)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:167)
at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:163)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:110)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:57)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.io.EOFException: \n not found: limit=0 content=…
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:240)
at okhttp3.internal.http1.Http1ExchangeCodec.readHeaderLine(Http1ExchangeCodec.java:242)
at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.java:213)
... 75 more
Client builder
public DefaultApi getCMApiClient() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(Level.BODY);
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
okHttpClient.addInterceptor(loggingInterceptor);
okHttpClient.retryOnConnectionFailure(true);
okHttpClient.addInterceptor(chain -> {
Request request = chain.request().newBuilder()
.addHeader("Connection", "close")
.addHeader("Transfer-Encoding", "chunked")
.build();
return chain.proceed(request);
});
return new Builder()
.client(okHttpClient.build())
.baseUrl("http://localhost:8080")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(DefaultApi.class);
}
openjdk 11.0.2
okhttp 3.14.2
win 10
I resolved this issue by downgrading the jar versions
@AjayVenkataRajuKarri to what version?
Any solution to this issue? I am facing the same issue with latest version of OKHttp.
@jkarnam executable test case? Please open a new issue if you can create one. Otherwise this is typically a connection canceled by the server.
Hi @swankjesse Swankjesse,
Thanks for your reply.
Here is my code snippet. I am trying to use PKCS12 certifiate. Using Conscrypt security provider will not give issue. But other HTTP/1.1 connection is not working. Tried with OKHttp 3.14.9 /4.8.0 and JDK1.8.0_201
public NotificationStatus sendSilentPushNotification(String data, String url, String certPath, String passwd, String deviceId, boolean silent) throws Exception {
NotificationStatus notifyStatus = null;
log.info("PAYLOAD: "+ data);
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, data);
String uuid = UUID.randomUUID().toString();
url = url + deviceId;
notifyStatus = new NotificationStatus();
Builder builder = new okhttp3.Request.Builder()
.url(url)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("apns-topic", "abcd.xyz.com")
.addHeader(":method", "POST")
.header(":path", "/3/device/"+deviceId)
.addHeader(":scheme", "https")
.addHeader("host", "api.push.apple.com")
.addHeader("apns-id", uuid)
.addHeader("apns-push-type", "background")
.header("Connection", "close");
if(silent) {
builder.addHeader("apns-expiration", "0")
.addHeader("apns-priority", "5");
}
Request request = builder.build();
try {
// Security.insertProviderAt(Conscrypt.newProvider(), 1);//TO use http2 with okHttp
OkHttpClient httpsClient = getOkHttpServiceClient(certPath, passwd);
Response response = httpsClient.newCall(request).execute();
if (!response.isSuccessful())
throw new RuntimeException("Unexpected code " + response);
log.info("Protocol: "+ response.protocol());
log.info("Success: "+ response.isSuccessful());
log.info("Body: "+ response.body().toString());
log.info("Response Code: "+ response.code());
notifyStatus.setErrorcode(0);
notifyStatus.setStatuscode(response.code());
} catch (Exception ex) {
log.error("ERROR: In Http2WithOkHttp.sendSilentPushNotification: ", ex);
notifyStatus.setErrorcode(0);
notifyStatus.setStatuscode(100);
}
return notifyStatus;
}
public OkHttpClient getOkHttpServiceClient(String certPath, String password) throws Exception{
FileInputStream stream = null;
final SSLContext sslContext;
try {
stream = new FileInputStream(certPath);
final KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
keyStore.load(stream, password.toCharArray());
String ksAlg = KeyManagerFactory.getDefaultAlgorithm();
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(ksAlg);
kmf.init(keyStore, password.toCharArray());
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(ksAlg);
trustManagerFactory.init((KeyStore) null);
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
// Get the SSLContext to help create SSLSocketFactory
sslContext = SSLContext.getInstance("TLS");
//sslContext.init(null, new TrustManager[] { trustManager }, null);// Reading from direct certs
sslContext.init(kmf.getKeyManagers(), trustManagers, null); //Reading from ca certs.
return new OkHttpClient().newBuilder().connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManager)
.build();
} catch (FileNotFoundException e) {
throw new RuntimeIOException(e);
} finally {
HttpUtilities.close(stream);
}
}
@jkarnam this isn’t a standalone executable test case. Can you do something that starts with this file?
https://gist.github.com/swankjesse/981fcae102f513eb13ed
@swankjesse , Thanks for quick reply. I am using a PKCS12 certificate for apple push notifications here. Sorry, I believe I cannot provide that online.
Apple's push service is HTTP/2 only if I understand correctly
So HTTP/1.1 is not likely to work
@jkarnam executable test case? Please open a new issue if you can create one. Otherwise this is typically a connection canceled by the server.
Hello, i don't think this is typically a connection canceled by the server. Because when i try to read stream byte by byte, no errors.
The OkHttpClient's default request protocol is HTTP2.0. Some Web Services are required HTTP1.1 requests.
Add protocols(listOf(Protocol.HTTP_1_1)) line to your OkHttpClient.
Example;
val okHttpClient = OkHttpClient.Builder()
.protocols(listOf(Protocol.HTTP_1_1))
.readTimeout(40, TimeUnit.SECONDS)
.connectTimeout(40, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
.retryOnConnectionFailure(true)
.build()
Most helpful comment
Here's your fix: