Сброшен поток OkHttp Android: HTTP_1_1_REQUIRED

Мы разрабатываем приложение для Android, которое должно использовать Http / 2 для подключения к нашей службе приложений Azure. В службе приложений Azure у нас включен протокол Http / 2, выполнив действия, описанные в следующем сообщении в блоге: https://blogs.msdn.microsoft.com/appserviceteam/2018/04/13/announcing-http2-support-in-azure-app-service/

Наши запросы защищены взаимным SSL, поэтому приложение должно отправлять свой сертификат клиента.

Когда мы пытаемся выполнить вызов нашей службы приложения с помощью OkHttp, мы всегда получаем следующую ошибку и трассировку стека. Когда мы пытаемся вызвать твиттер API с тем же кодом Android, это работает.

Кто-нибудь знает, как это исправить?

Мы используем OkHttp версии 3.10.0.

Stacktrace:

    06-08 15:54:00.173 31318-31351/be.wgkovl.evdt W/be.wgkovl.evdt.utils.BaseService: stream was reset: HTTP_1_1_REQUIREDokhttp3.internal.http2.StreamResetException: stream was reset: HTTP_1_1_REQUIRED
                at okhttp3.internal.http2.Http2Stream.takeResponseHeaders(Http2Stream.java:153) ~[na:0.0]
                at okhttp3.internal.http2.Http2Codec.readResponseHeaders(Http2Codec.java:125) ~[na:0.0]
                at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[na:0.0]
                at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[na:0.0]
                at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[na:0.0]
                at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[na:0.0]
                at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[na:0.0]
                at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[na:0.0]
                at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200) ~[na:0.0]
                at okhttp3.RealCall.execute(RealCall.java:77) ~[na:0.0]
                at be.wgkovl.evdt.utils.BaseService.executeRequest(BaseService.java:277) ~[na:0.0]
                at be.wgkovl.evdt.service.UserManagementService$1.doInBackground(UserManagementService.java:123) ~[na:0.0]
                at be.wgkovl.evdt.service.UserManagementService$1.doInBackground(UserManagementService.java:101) ~[na:0.0]
                at android.os.AsyncTask$2.call(AsyncTask.java:295) ~[na:0.0]
                at java.util.concurrent.FutureTask.run(FutureTask.java:237) ~[na:0.0]
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) ~[na:0.0]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) ~[na:0.0]
                at java.lang.Thread.run(Thread.java:818) ~[na:0.0]


person dpeeters    schedule 09.06.2018    source источник


Ответы (2)


добавить эту строку в построитель

.protocols(Util.immutableList(Protocol.HTTP_1_1))

нравится

 private OkHttpClient client = new OkHttpClient.Builder()
            .protocols(Util.immutableList(Protocol.HTTP_1_1))
            .build();
person user2563494    schedule 21.01.2020

HTTP / 2 на самом деле не поддерживает клиентские сертификаты в настоящее время, особенно когда такие соединения применяются только к некоторым ресурсам на сервере. Существует предложение разрешить это, но он еще не стандартизирован и, AFAIK, еще не поддерживается какой-либо реализацией.

Пока это не поддерживается, правильный ответ - предложить перейти на HTTP / 1.1 с кодом ошибки HTTP_1_1_REQUIRED, и клиент должен повторить попытку с HTTP / 1.1.

Другие реализации делают это так же, как и Azure.

person Barry Pollard    schedule 10.06.2018
comment
Это странно. Потому что, когда я подключаюсь к своей конечной точке Azure с сертификатом клиента с помощью браузера Edge. Он правильно возвращает ответ, и я вижу, что HTTP / 2 используется с сетевым монитором ... Это означает, что он поддерживает сертификат клиента. - person dpeeters; 11.06.2018
comment
Дополнительная информация: сертификаты клиентов применяются ко всем ресурсам на сервере. Не только для определенных конечных точек. - person dpeeters; 11.06.2018