diff --git a/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceHttpTest.kt b/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceHttpTest.kt index 75d2e6775..4e714dae0 100644 --- a/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceHttpTest.kt +++ b/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceHttpTest.kt @@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit import mockwebserver3.MockResponse import mockwebserver3.MockWebServer import mockwebserver3.junit5.StartStop +import okhttp3.Headers import okhttp3.OkHttpClientTestRule import okhttp3.RecordingEventListener import okhttp3.Request @@ -259,6 +260,56 @@ class EventSourceHttpTest { ) } + @Test + fun sseReauths() { + client = + client + .newBuilder() + .authenticator { route, response -> + response.request + .newBuilder() + .header("Authorization", "XYZ") + .build() + }.build() + server.enqueue( + MockResponse( + code = 401, + body = "{\"error\":{\"message\":\"No auth credentials found\",\"code\":401}}", + headers = Headers.headersOf("content-type", "application/json"), + ), + ) + server.enqueue( + MockResponse( + body = + """ + |data: hey + | + | + """.trimMargin(), + headers = Headers.headersOf("content-type", "text/event-stream"), + ), + ) + val source = newEventSource() + assertThat(source.request().url.encodedPath).isEqualTo("/") + listener.assertOpen() + listener.assertEvent(null, null, "hey") + listener.assertClose() + } + + @Test + fun sseWithoutAuthenticator() { + server.enqueue( + MockResponse( + code = 401, + body = "{\"error\":{\"message\":\"No auth credentials found\",\"code\":401}}", + headers = Headers.headersOf("content-type", "application/json"), + ), + ) + val source = newEventSource() + assertThat(source.request().url.encodedPath).isEqualTo("/") + listener.assertFailure(code = 401, message = "{\"error\":{\"message\":\"No auth credentials found\",\"code\":401}}") + } + private fun newEventSource(accept: String? = null): EventSource { val builder = Request diff --git a/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceRecorder.kt b/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceRecorder.kt index 00abcf749..e18a278fd 100644 --- a/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceRecorder.kt +++ b/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourceRecorder.kt @@ -67,7 +67,7 @@ class EventSourceRecorder : EventSourceListener() { response: Response?, ) { get().log("[ES] onFailure", Platform.INFO, t) - events.add(Failure(t, response)) + events.add(Failure(t, response, t?.message ?: response?.body?.string())) drainCancelQueue(eventSource) } @@ -103,10 +103,16 @@ class EventSourceRecorder : EventSourceListener() { nextEvent() as Closed } - fun assertFailure(message: String?) { + fun assertFailure( + message: String?, + code: Int? = null, + ) { val event = nextEvent() as Failure + if (code != null) { + assertThat(event.response?.code).isEqualTo(code) + } if (message != null) { - assertThat(event.t!!.message).isEqualTo(message) + assertThat(event.message).isEqualTo(message) } else { assertThat(event.t).isNull() } @@ -120,6 +126,7 @@ class EventSourceRecorder : EventSourceListener() { internal data class Failure( val t: Throwable?, val response: Response?, + val message: String?, ) internal object Closed diff --git a/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourcesHttpTest.kt b/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourcesHttpTest.kt index 22573aed1..9645e7f2a 100644 --- a/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourcesHttpTest.kt +++ b/okhttp-sse/src/test/java/okhttp3/sse/internal/EventSourcesHttpTest.kt @@ -15,9 +15,12 @@ */ package okhttp3.sse.internal +import assertk.assertThat +import assertk.assertions.isEqualTo import mockwebserver3.MockResponse import mockwebserver3.MockWebServer import mockwebserver3.junit5.StartStop +import okhttp3.Headers import okhttp3.OkHttpClientTestRule import okhttp3.Request import okhttp3.sse.EventSources.processResponse @@ -60,11 +63,7 @@ class EventSourcesHttpTest { ).setHeader("content-type", "text/event-stream") .build(), ) - val request = - Request - .Builder() - .url(server.url("/")) - .build() + val request = Request.Builder().url(server.url("/")).build() val response = client.newCall(request).execute() processResponse(response, listener) listener.assertOpen() @@ -87,14 +86,46 @@ class EventSourcesHttpTest { .build(), ) listener.enqueueCancel() // Will cancel in onOpen(). - val request = - Request - .Builder() - .url(server.url("/")) - .build() + val request = Request.Builder().url(server.url("/")).build() val response = client.newCall(request).execute() processResponse(response, listener) listener.assertOpen() listener.assertFailure("canceled") } + + @Test + fun failureWith401IsReadable() { + server.enqueue( + MockResponse( + code = 401, + body = "{\"error\":{\"message\":\"No auth credentials found\",\"code\":401}}", + headers = Headers.headersOf("content-type", "application/json"), + ), + ) + server.enqueue( + MockResponse( + body = + """ + |data: hey + | + | + """.trimMargin(), + headers = Headers.headersOf("content-type", "text/event-stream"), + ), + ) + var request = Request.Builder().url(server.url("/")).build() + repeat(2) { + val response = client.newCall(request).execute() + + if (response.code == 401) { + assertThat(response.body.string()).isEqualTo("{\"error\":{\"message\":\"No auth credentials found\",\"code\":401}}") + request = request.newBuilder().header("Authorization", "XYZ").build() + } else { + processResponse(response, listener) + listener.assertOpen() + listener.assertEvent(null, null, "hey") + listener.assertClose() + } + } + } }