How to catch okhttp3 WebSocket network activity using okhttp3.Interceptor?

I have an okhttp3 (3.9.1) WebSocket instance and would like to view all it's network requests and responses. I tried to add some okhttp3.Interceptor instances to OkHttpClient instance before creating WebSocket on it but had no luck in viewing network activity. Here's sample code which demonstrates what I've tried to do:

package sample

import okhttp3.*
import java.io.IOException
import java.lang.Thread.sleep

fun main(args: Array<String>) {
    val listener = object : WebSocketListener() {
        override fun onMessage(webSocket: WebSocket?, text: String?) {
            println("Got server message: $text")
        }
    }

    val dummyInterceptor = Interceptor { chain ->
        val request = chain.request()
        val response = chain.proceed(request)
        println("Dummy interceptor fired!\n\nRequest: ${request.headers()}\nResponse: ${response.headers()}")
        return@Interceptor response
    }

    val dummyNetworkInterceptor = Interceptor { chain ->
        val request = chain.request()
        val response = chain.proceed(request)
        println("Dummy network interceptor fired!\n\nRequest: ${request.headers()}\nResponse: ${response.headers()}")
        return@Interceptor response
    }

    val okHttpClient = OkHttpClient.Builder()
            .addInterceptor(dummyInterceptor)
            .addNetworkInterceptor(dummyNetworkInterceptor)
            .build()

    val request = Request.Builder().url("ws://echo.websocket.org").build()

    val webSocket = okHttpClient.newWebSocket(request, listener)

    webSocket.send("Hello1!")
    webSocket.send("Hello2!")
    webSocket.send("Hello3!")

    sleep(2000) //Just for this sample to ensure all WS requests done
    println("\n\n\tSome network activity\n\n")

    okHttpClient.newCall(Request.Builder().get().url("http://echo.websocket.org").build()).enqueue(object : Callback {
        override fun onFailure(call: Call?, exc: IOException?) {
            println("OnFailure: ${exc?.message}")
        }

        override fun onResponse(call: Call?, response: Response?) {
            println("OnResponse: ${response?.headers()}")
        }
    })
}

I tried to dive into okhttp3 source code and didn't find any reason why any of my interceptors doesn't fire on WS requests but works perfectly for any OkHttpClient request.

Is it a bug in okhttp3 or am I doing something wrong or it's just not possible to monitor WS requests using okhttp3.Interceptor?

Upvotes: 3

Views: 3181

Answers (2)

amitavk
amitavk

Reputation: 1336

It isn't possible at this point, there's a feature request open for OkHttp but it isn't getting much traction: https://github.com/square/okhttp/issues/4192

Upvotes: 1

zsmb13
zsmb13

Reputation: 89588

WebSocket calls made with OkHttp don't use the interceptor chains that HTTP calls do, therefore you can't monitor them through interceptors.

I've faced this issue before myself, and so I looked at the source code and found the following then:

  • The regular HTTP calls go through the getResponseWithInterceptorChain() method in the RealCall class, which quite clearly starts the chained call of interceptors for each request.
  • The okhttp3.internal.ws package that includes the implementation of the WebSocket handling contains no code related to interceptors.

And really, interceptors catching WebSocket requests wouldn't really make sense in the first place. The Request that you can obtain in an interceptor represents an HTTP request, which WebSocket messages are not.

Upvotes: 4

Related Questions