Доступ к основным потокам TCP во время вызова с помощью OkHttp - PullRequest
1 голос
/ 04 июля 2019

Я реализовал клиент для Docker API.

Конечная точка для присоединения к выводу контейнера немного необычна тем, что вам нужно перехватить базовый поток TCP и использовать его для чтения вывода из контейнера.

Документация для конечной точки API: https://docs.docker.com/engine/api/v1.37/#operation/ContainerAttach (К сожалению, версия веб-сокета этой конечной точки не работает на OS X , поэтому я не могу ее использовать.)

Я использовал этот код , чтобы получить доступ к потокам вплоть до OkHttp v3.13.1 включительно:

class ConnectionHijacker : Interceptor {
    var source: BufferedSource? = null
    var sink: BufferedSink? = null

    override fun intercept(chain: Interceptor.Chain): Response {
        val connection = chain.connection() as RealConnection
        val streams = connection.newWebSocketStreams(connection.allocations.single().get())

        sink = streams.sink
        source = streams.source

        return chain.proceed(chain.request())
    }
}

Это прекрасно работает.

Однако в более поздних версиях API OkHttp значительно изменился. Нечто подобное работает с v1.13.1 и компилируется с более поздними версиями, но не дает никакого вывода в потоке:

class ConnectionHijacker : Interceptor {
    var source: BufferedSource? = null
    var sink: BufferedSink? = null

    override fun intercept(chain: Interceptor.Chain): Response {
        val connection = chain.connection() as RealConnection

        sink = connection.sink
        source = connection.source

        return chain.proceed(chain.request())
    }

    private val RealConnection.sink: BufferedSink
        get() {
            val property = RealConnection::class.declaredMemberProperties.single { it.name == "sink" }
            property.isAccessible = true
            return property.get(this) as BufferedSink
        }

    private val RealConnection.source: BufferedSource
        get() {
            val property = RealConnection::class.declaredMemberProperties.single { it.name == "source" }
            property.isAccessible = true
            return property.get(this) as BufferedSource
        }
}

Я понимаю, что это взлом на вершине другого взлома и совершенно не поддерживается, но есть ли у кого-нибудь идеи о том, как я могу сделать эту работу?

1 Ответ

1 голос
/ 04 июля 2019

Если вы можете использовать HTTP / 2, взгляните на RequestBody.isDuplex () . Это позволит вам получить доступ к выводу запроса и ответному вводу, чтобы делать то, что вам нравится.

...