Menu

OkHttp, HTTP/2 & NGINX 1.9.5

OkHttp’s HTTP/2 doesn’t interop with NGINX 1.9.5. HTTP requests made from OkHttp to impacted NGINX servers will fail like this:

java.io.IOException: stream was reset: PROTOCOL_ERROR  
    at com.squareup.okhttp.internal.spdy.SpdyStream.getResponseHeaders(SpdyStream.java:145)
    at com.squareup.okhttp.internal.http.SpdyTransport.readResponseHeaders(SpdyTransport.java:104)
    at com.squareup.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:830)
    at com.squareup.okhttp.internal.http.HttpEngine.access$200(HttpEngine.java:95)
    at com.squareup.okhttp.internal.http.HttpEngine$NetworkInterceptorChain.proceed(HttpEngine.java:823)
    at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:684)
    at com.squareup.okhttp.Call.getResponse(Call.java:272)

They’ve merged a fix. In the interim, you can either downgrade your NGINX or disable HTTP/2 in OkHttp:

OkHttpClient client = new OkHttpClient();

// Disable HTTP/2 for interop with NGINX 1.9.5.
// TODO: remove this hack after 2015-12-31.
client.setProtocols(Collections.singletonList(Protocol.HTTP_1_1));  

HPACK is what HTTP/2 uses to compress headers. It’s a bit tricky to get right, partially because there are multiple ways to encode headers. In this case OkHttp’s compression strategy triggered a different code path than the major browsers.