Reputation: 165
I've implemented a client for the Docker API.
The endpoint for attaching to a container's output is a bit unusual in that you need to hijack the underlying TCP stream and use that to read the output from the container.
Documentation for API endpoint: https://docs.docker.com/engine/api/v1.37/#operation/ContainerAttach (Unfortunately the web socket version of this endpoint is broken on OS X, so I can't use that.)
I've been using this code to get access to the streams up to and including 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())
}
}
This works perfectly.
However, in more recent versions, the OkHttp API has changed significantly. Something like this works with v1.13.1 and compiles with later versions, but does not give me any output in the stream:
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
}
}
I realise this is a hack on top of another hack and completely unsupported, but does anyone have any ideas on how I can make this work?
Upvotes: 1
Views: 240
Reputation: 40603
If you can use HTTP/2, then take a look at RequestBody.isDuplex(). It'll let you access the request output and the response input to do what you like.
Upvotes: 1