OkHttp 3.14.0 introduced support for duplex calls, where request and response bodies are transmitted simultaneously. This is useful for interactive conversations (e.g., gRPC) within a single HTTP call.
To implement a duplex call, override RequestBody.isDuplex() to return true.
Important considerations for duplex calls:
- HTTP/2 Requirement: Duplex calls require HTTP/2. If the connection falls back to HTTP/1, the call will fail.
- Thread Safety in
writeTo(): The RequestBody.writeTo() method may retain a reference to the provided sink and hand it off to another thread to write to it after the method returns. - Interleaved Events:
EventListener may see requests and responses interleaved (e.g., responseHeadersStart() followed by requestBodyEnd() on the same call). These events may be triggered by different threads. - Interceptor Caution: Interceptors that rewrite or replace the request body may interfere with duplex calls. Interceptors should check
RequestBody.isDuplex() and avoid accessing the request body when it is true.
// Example pattern for a duplex request body
class MyDuplexBody : RequestBody() {
override fun contentType(): MediaType? = "application/octet-stream".toMediaType()
override fun isDuplex(): Boolean = true
override fun writeTo(sink: BufferedSink) {
// Implementation may hand off the sink to another thread
}
}