Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue #4382 - Support HTTP/1 upgrade to HTTP/2 in HttpClient.
* Moved implementation of UpgradeTo from HTTP2ServerConnection to HTTP2Connection, since now also the client connection can be upgraded to. * Split HTTP2Session.newStream(), since now the client must be able to create the implicit stream 1 corresponding to the HTTP/1.1 upgrade request, so that the HTTP/2 response after the upgrade finds the stream. * The HTTP/1.1 upgrade mechanism has been generalized. Before it was based on HttpConnectionUpgrader and a hook in HttpChannelOverHTTP.exchangeTerminating(). Now it is based on UpgradeProtocolHandler that when sees a 101 response it will trigger the upgrade mechanism. * Introduced ConnectionPool.accept(Connection) to transfer a connection from the HTTP/1.1 connection pool to the HTTP/2 connection pool after the upgrade. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
- Loading branch information
Showing
33 changed files
with
751 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
jetty-client/src/main/java/org/eclipse/jetty/client/UpgradeProtocolHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// | ||
// ======================================================================== | ||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. | ||
// | ||
// This program and the accompanying materials are made available under | ||
// the terms of the Eclipse Public License 2.0 which is available at | ||
// https://www.eclipse.org/legal/epl-2.0 | ||
// | ||
// This Source Code may also be made available under the following | ||
// Secondary Licenses when the conditions for such availability set | ||
// forth in the Eclipse Public License, v. 2.0 are satisfied: | ||
// the Apache License v2.0 which is available at | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 | ||
// ======================================================================== | ||
// | ||
|
||
package org.eclipse.jetty.client; | ||
|
||
import java.util.List; | ||
|
||
import org.eclipse.jetty.client.api.Request; | ||
import org.eclipse.jetty.client.api.Response; | ||
import org.eclipse.jetty.client.api.Result; | ||
import org.eclipse.jetty.http.HttpField; | ||
import org.eclipse.jetty.http.HttpHeader; | ||
import org.eclipse.jetty.http.HttpStatus; | ||
import org.eclipse.jetty.io.EndPoint; | ||
import org.eclipse.jetty.util.Callback; | ||
|
||
/** | ||
* <p>A protocol handler that handles HTTP 101 responses.</p> | ||
*/ | ||
public class UpgradeProtocolHandler implements ProtocolHandler | ||
{ | ||
private final List<String> protocols = List.of("websocket", "h2c"); | ||
|
||
@Override | ||
public String getName() | ||
{ | ||
return "upgrade"; | ||
} | ||
|
||
@Override | ||
public boolean accept(Request request, Response response) | ||
{ | ||
boolean upgraded = HttpStatus.SWITCHING_PROTOCOLS_101 == response.getStatus(); | ||
boolean accepted = false; | ||
if (upgraded) | ||
accepted = acceptHeaders(request, response); | ||
return upgraded && accepted; | ||
} | ||
|
||
protected boolean acceptHeaders(Request request, Response response) | ||
{ | ||
HttpField responseUpgrade = response.getHeaders().getField(HttpHeader.UPGRADE); | ||
if (responseUpgrade != null && protocols.stream().anyMatch(responseUpgrade::contains)) | ||
return true; | ||
// The response may not contain the Upgrade header, so check the request. | ||
HttpField requestUpgrade = request.getHeaders().getField(HttpHeader.UPGRADE); | ||
return requestUpgrade != null && protocols.stream().anyMatch(requestUpgrade::contains); | ||
} | ||
|
||
@Override | ||
public Response.Listener getResponseListener() | ||
{ | ||
return new Response.Listener.Adapter() | ||
{ | ||
@Override | ||
public void onComplete(Result result) | ||
{ | ||
HttpResponse response = (HttpResponse)result.getResponse(); | ||
HttpRequest request = (HttpRequest)response.getRequest(); | ||
if (result.isSucceeded()) | ||
{ | ||
try | ||
{ | ||
HttpConversation conversation = request.getConversation(); | ||
HttpUpgrader upgrader = (HttpUpgrader)conversation.getAttribute(HttpUpgrader.class.getName()); | ||
if (upgrader == null) | ||
throw new HttpResponseException("101 response without " + HttpUpgrader.class.getSimpleName(), response); | ||
EndPoint endPoint = (EndPoint)conversation.getAttribute(EndPoint.class.getName()); | ||
if (endPoint == null) | ||
throw new HttpResponseException("Upgrade without " + EndPoint.class.getSimpleName(), response); | ||
upgrader.upgrade(response, endPoint, Callback.from(Callback.NOOP::succeeded, x -> forwardFailureComplete(request, null, response, x))); | ||
} | ||
catch (Throwable x) | ||
{ | ||
forwardFailureComplete(request, null, response, x); | ||
} | ||
} | ||
else | ||
{ | ||
forwardFailureComplete(request, result.getRequestFailure(), response, result.getResponseFailure()); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
private void forwardFailureComplete(HttpRequest request, Throwable requestFailure, Response response, Throwable responseFailure) | ||
{ | ||
HttpConversation conversation = request.getConversation(); | ||
conversation.updateResponseListeners(null); | ||
List<Response.ResponseListener> responseListeners = conversation.getResponseListeners(); | ||
ResponseNotifier notifier = new ResponseNotifier(); | ||
notifier.forwardFailure(responseListeners, response, responseFailure); | ||
notifier.notifyComplete(responseListeners, new Result(request, requestFailure, response, responseFailure)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.