androidnginxretrofitokhttpalpn

http2 doesn't seem to be working with OkHttp3 and retrofit2


I just upgraded from okhttp2 + retrofit to okhttp3 + retrofit2 but can't get the http2 working on Android client.

My server is running nginx 1.14.0 with http2 enabled. (iOS client is working fine on http2)

Here's the code which creates the okhttp client

    private static OkHttpClient createOkHttpClient(Application app,
                                               NetworkInterceptor networkInterceptor,
                                               HttpLoggingInterceptor httpLoggingInterceptor) {
    // Install an HTTP cache in the application cache directory.
    File  cacheDir = new File(app.getCacheDir(), "http");
    Cache cache    = new Cache(cacheDir, DISK_CACHE_SIZE);

    Security.insertProviderAt(
            new org.conscrypt.OpenSSLProvider(), 1);

    OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient().newBuilder()
            .cache(cache)
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .callTimeout(30, TimeUnit.SECONDS)
            .protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
            .followRedirects(true)
            .followSslRedirects(true)
            .addInterceptor(networkInterceptor)
            .addInterceptor(httpLoggingInterceptor);

    if (BuildConfig.DEBUG) {
        okHttpClientBuilder.addNetworkInterceptor(new StethoInterceptor());
    }
    return okHttpClientBuilder.build();
}

I'm using dagger 2 to create Api with retrofit 2.

My testing device is running Android 8.1.

I've read the documentation, and this setup should be running http2. Is there something wrong with my implementation?


Solution

  • I got it to working after rebuilding nginx. The code at the client side is fine.

    The default nginx shipped with ubuntu 14.04 doesn't support http2 out of the box for google clients. It uses NPN and not ALPN. In order to support APLN we need to rebuild openssl and nginx.

    Rebuild openssl package with ALPN support(OpenSSL 1.0.2h 3 May 2016)

    $ wget -c https://www.openssl.org/source/openssl-1.0.2h.tar.gz
    $ tar xf openssl-1.0.2h.tar.gz -C /usr/local/
    $ cd /usr/local/openssl-1.0.2h
    $ ./config
    $ make depend
    $ make
    $ make test
    $ make install
    $ mv /usr/bin/openssl /usr/bin/openssl_1.0.1e
    $ ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
    $ openssl version
    OpenSSL 1.0.2h  3 May 2016
    

    Rebuild nginx using the new openssl

    $ sudo apt-get install libpcre3-dev libssl-dev libxml2-dev libxslt-dev libgd-dev libgeoip-dev
    $ wget http://nginx.org/download/nginx-1.14.2.tar.gz
    $ tar -xvzf nginx-1.14.2.tar.gz 
    $ cd nginx-1.14.2/
    $ ./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --with-openssl=/usr/local/openssl-1.0.2h/
    $ sudo make
    $ sudo make install
    $ nginx -V
    nginx version: nginx/1.14.2
    built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
    built with OpenSSL 1.0.2h  3 May 2016
    TLS SNI support enabled
    

    Just restart nginx after this and it should be working fine.