Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SocketTimeoutException in MockWebServer while using custom authenticator and mocking 401 Unauthorized response #3213

Closed
anidotnet opened this issue Mar 8, 2017 · 3 comments

Comments

@anidotnet
Copy link

anidotnet commented Mar 8, 2017

Below test throws SocketTimeoutException without any proper reason.

    @Test
    public void test() throws IOException {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(100, TimeUnit.MILLISECONDS)
                .readTimeout(100, TimeUnit.MILLISECONDS)
                .authenticator(new Authenticator() {
                    public Request authenticate(Route route, Response response) throws IOException {
                        String credential = Credentials.basic("test", "test");
                        return response.request().newBuilder().header("Authorization", credential).build();
                    }
                })
                .build();
        MockWebServer webServer = new MockWebServer();

        Request request = new Request.Builder()
                .url(webServer.url("/"))
                .build();

        webServer.enqueue(new MockResponse()
                .setBody("{}")
                .setResponseCode(401));
        String response = client.newCall(request).execute().body().string();
        assertEquals(response, "{}");
    }

But the test passes if I set the response code in MockResponse to 200 as below

webServer.enqueue(new MockResponse()
                .setBody("{}")
                .setResponseCode(200));

Again the above test never completes if I don't put timeout settings for OkHttpClient as below

OkHttpClient client = new OkHttpClient.Builder()
//                .connectTimeout(100, TimeUnit.MILLISECONDS)
//                .readTimeout(100, TimeUnit.MILLISECONDS)
                .authenticator(new Authenticator() {
                    public Request authenticate(Route route, Response response) throws IOException {
                        String credential = Credentials.basic("test", "test");
                        return response.request().newBuilder().header("Authorization", credential).build();
                    }
                })
                .build();

The test keep waiting at the line client.newCall(request).execute().body().string();

Here is the stacktrace and log for the SocketTimeoutException

Mar 08, 2017 12:15:03 PM okhttp3.mockwebserver.MockWebServer$2 execute
INFO: MockWebServer[46822] starting to accept connections
Mar 08, 2017 12:15:03 PM okhttp3.mockwebserver.MockWebServer$2 execute
INFO: MockWebServer[48936] starting to accept connections
Mar 08, 2017 12:15:03 PM okhttp3.mockwebserver.MockWebServer$3 processOneRequest
INFO: MockWebServer[48936] received request: GET / HTTP/1.1 and responded: HTTP/1.1 401 Client Error
Mar 08, 2017 12:15:03 PM okhttp3.mockwebserver.MockWebServer$2 acceptConnections
INFO: MockWebServer[46822] done accepting connections: Socket closed

java.net.SocketTimeoutException: timeout

	at okio.Okio$4.newTimeoutException(Okio.java:227)
	at okio.AsyncTimeout.exit(AsyncTimeout.java:284)
	at okio.AsyncTimeout$2.read(AsyncTimeout.java:240)
	at okio.RealBufferedSource.indexOf(RealBufferedSource.java:325)
	at okio.RealBufferedSource.indexOf(RealBufferedSource.java:314)
	at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:210)
	at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
	at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:67)
	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:179)
	at okhttp3.RealCall.execute(RealCall.java:63)
	at org.dizitart.no2.sync.WormholeUserTemplateTest.test(WormholeUserTemplateTest.java:140)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.net.SocketTimeoutException: Read timed out
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:170)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at okio.Okio$2.read(Okio.java:138)
	at okio.AsyncTimeout$2.read(AsyncTimeout.java:236)
	... 49 more

@swankjesse
Copy link
Member

When you install an Authenticator, OkHttp will retry requests that failed with a 401 Unauthorized response. But your MockWebServer only has a single response to return, so nothing completes. This is working as designed.

@anidotnet
Copy link
Author

@swankjesse so how do I make OkHttp not to retry after a 401 response?

@swankjesse
Copy link
Member

Remove your Authenticator or change it to return null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants