Принудительное немедленное небезопасное соединение HTTP2 с Java HttpClient - PullRequest
0 голосов
/ 26 сентября 2018

Используя в качестве клиента только стандартную библиотеку Java, как можно установить небезопасное HTTP / 2-соединение с предварительным знанием , что будет использоваться эта версия протокола?Т.е. без отправки запроса на обновление сначала через HTTP / 1.1.

Я пытался использовать утилиты в java.net.http, вызывать version(HttpClient.Version.HTTP_2) по запросу и сборщики клиентов, однако первоначальный запрос всегда отправляется через HTTP /1.1 с заголовком обновления.Пока что единственный способ заставить версию 2 с самого начала, похоже, использовать защищенное соединение через https (чего я хотел бы избежать).

Я также хотел бы придерживаться использования только классоввключены в OpenJDK 11 (нетто или что-то подобное).

1 Ответ

0 голосов
/ 19 марта 2019

Боюсь, что это невозможно в HTTP-клиенте Java 11.

Наиболее релевантный внутренний класс JDK: Http2Connection.java .В нем перечислены три случая «создания», которые мы ожидаем для HTTP / 2-соединений:

  1. обновленное HTTP / 1.1 обычное TCP-соединение
  2. предшествующее знание непосредственно созданного простого TCP-соединения
  3. непосредственно созданное соединение HTTP / 2 SSL, которое использует ALPN.

Нас интересует случай 2. Есть код для этого:

/**
 * Cases 2) 3)
 *
 * request is request to be sent.
 */
private Http2Connection(HttpRequestImpl request,
                        Http2ClientImpl h2client,
                        HttpConnection connection)
    throws IOException
{
    ...
}

Увы, этот конструкторфактически используется только из метода для безопасных соединений:

// Requires TLS handshake. So, is really async
static CompletableFuture<Http2Connection> createAsync(HttpRequestImpl request,
                                                      Http2ClientImpl h2client,
                                                      Exchange<?> exchange) {
    assert request.secure();
    AbstractAsyncSSLConnection connection = (AbstractAsyncSSLConnection)
    ...
    return connection.connectAsync(exchange)
              .thenCompose(unused -> connection.finishConnect())
              .thenCompose(unused -> checkSSLConfig(connection))
              .thenCompose(notused-> {
                  CompletableFuture<Http2Connection> cf = new MinimalFuture<>();
                  try {
                      Http2Connection hc = new Http2Connection(request, h2client, connection);
                      cf.complete(hc);
                  } catch (IOException e) {
                      cf.completeExceptionally(e);
                  }
                  return cf; } );

Кажется, что конструкторы не-TLS вызываются только при обновлении соединения HTTP 1.1.

Я просмотрел многиеиз других классов тоже.Я не вижу ничего, что указывало бы на то, что можно установить согласование HTTP / 2-соединений в открытом тексте без обновления HTTP 1.1 в клиенте JDK 11.

То, что я нахожу, очень соответствует описанию API в javadocs для HttpClient.Builder , в котором говорится только о выборе HTTP / 2 в качестве версии:

Если установлено значение HTTP / 2, то каждый запрос будет пытаться обновиться до HTTP / 2.Если обновление выполнено успешно, то ответ на этот запрос будет использовать HTTP / 2, а все последующие запросы и ответы на тот же сервер происхождения будут использовать HTTP / 2.Если обновление завершится неудачно, ответ будет обработан с использованием HTTP / 1.1

В повторном использовании соединения HTTP / 2 происходит много интересного.Например, при одновременном обновлении одновременных запросов остается только один для последующего использования в «кэше» HTTP / 2-соединения.Кэшированное соединение истечет, когда число потоков достигнет максимума, который составляет ~ 2 ^ 31-1, так что дальнейшие запросы не превысят его, но существующие потоки останутся открытыми.Это много потоков.Я думаю, что если ваш вариант использования похож на мой - клиент веб-службы в приложениях с очень длительным запуском - тогда стоимость обновления практически только для первого запроса незначительна.Я все еще хотел бы устранить это, главным образом для простоты, но я начинаю думать, что оно того не стоит.

Как тот, кто спрашивает, я хотел бы придерживаться клиента JDK.Я просто упомяну, что бета-версия Apache HttpClient 5 поддерживает форсирование HTTP / 2 (HttpVersionPolicy.FORCE_HTTP_2).Я не могу давать дальнейшие рекомендации по этому поводу, потому что бета-версия не имеет много документации, и комментарии гораздо более редки, чем реализация JDK.Но если я попробую это сделать и добьюсь успеха, я обновлю свой ответ.

...