Lazily instantiate HttpServerUpgradeHandler.UpgradeCodec
Related: #3814 Motivation: To implement the support for an upgrade from cleartext HTTP/1.1 connection to cleartext HTTP/2 (h2c) connection, a user usually uses HttpServerUpgradeHandler. It does its job, but it requires a user to instantiate the UpgradeCodecs for all supported protocols upfront. It means redundancy for the connections that are not upgraded. Modifications: - Change the constructor of HttpServerUpgradeHandler - Accept UpgraceCodecFactory instead of UpgradeCodecs - The default constructor of HttpServerUpgradeHandler sets the maxContentLength to 0 now, which shouldn't be a problem because a usual upgrade request is a GET. - Update the examples accordingly Result: A user can instantiate Http2ServerUpgradeCodec and its related objects (Http2Connection, Http2FrameReader/Writer, Http2FrameListener, etc) only when necessary.
This commit is contained in:
parent
950da2eae1
commit
0ca65f1373
@ -17,21 +17,16 @@ package io.netty.handler.codec.http;
|
|||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.util.AsciiString;
|
|
||||||
import io.netty.util.ReferenceCountUtil;
|
import io.netty.util.ReferenceCountUtil;
|
||||||
import io.netty.util.ReferenceCounted;
|
import io.netty.util.ReferenceCounted;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import static io.netty.handler.codec.http.HttpResponseStatus.SWITCHING_PROTOCOLS;
|
import static io.netty.handler.codec.http.HttpResponseStatus.SWITCHING_PROTOCOLS;
|
||||||
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
|
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
|
||||||
|
import static io.netty.util.internal.ObjectUtil.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A server-side handler that receives HTTP requests and optionally performs a protocol switch if
|
* A server-side handler that receives HTTP requests and optionally performs a protocol switch if
|
||||||
@ -54,12 +49,6 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
* A codec that the source can be upgraded to.
|
* A codec that the source can be upgraded to.
|
||||||
*/
|
*/
|
||||||
public interface UpgradeCodec {
|
public interface UpgradeCodec {
|
||||||
/**
|
|
||||||
* Returns the name of the protocol supported by this codec, as indicated by the
|
|
||||||
* {@link HttpHeaderNames#UPGRADE} header.
|
|
||||||
*/
|
|
||||||
String protocol();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all protocol-specific headers required by this protocol for a successful upgrade.
|
* Gets all protocol-specific headers required by this protocol for a successful upgrade.
|
||||||
* Any supplied header will be required to appear in the {@link HttpHeaderNames#CONNECTION} header as well.
|
* Any supplied header will be required to appear in the {@link HttpHeaderNames#CONNECTION} header as well.
|
||||||
@ -87,6 +76,20 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
void upgradeTo(ChannelHandlerContext ctx, FullHttpRequest upgradeRequest, FullHttpResponse upgradeResponse);
|
void upgradeTo(ChannelHandlerContext ctx, FullHttpRequest upgradeRequest, FullHttpResponse upgradeResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link UpgradeCodec} for the requested protocol name.
|
||||||
|
*/
|
||||||
|
public interface UpgradeCodecFactory {
|
||||||
|
/**
|
||||||
|
* Invoked by {@link HttpServerUpgradeHandler} for all the requested protocol names in the order of
|
||||||
|
* the client preference. The first non-{@code null} {@link UpgradeCodec} returned by this method
|
||||||
|
* will be selected.
|
||||||
|
*
|
||||||
|
* @return a new {@link UpgradeCodec}, or {@code null} if the specified protocol name is not supported
|
||||||
|
*/
|
||||||
|
UpgradeCodec newUpgradeCodec(String protocol);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User event that is fired to notify about the completion of an HTTP upgrade
|
* User event that is fired to notify about the completion of an HTTP upgrade
|
||||||
* to another protocol. Contains the original upgrade request so that the response
|
* to another protocol. Contains the original upgrade request so that the response
|
||||||
@ -160,33 +163,44 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, UpgradeCodec> upgradeCodecMap;
|
private static final String UPGRADE_STRING = HttpHeaderNames.UPGRADE.toString();
|
||||||
|
|
||||||
private final SourceCodec sourceCodec;
|
private final SourceCodec sourceCodec;
|
||||||
|
private final UpgradeCodecFactory upgradeCodecFactory;
|
||||||
private boolean handlingUpgrade;
|
private boolean handlingUpgrade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the upgrader with the supported codecs.
|
* Constructs the upgrader with the supported codecs.
|
||||||
|
* <p>
|
||||||
|
* The handler instantiated by this constructor will reject an upgrade request with non-empty content.
|
||||||
|
* It should not be a concern because an upgrade request is most likely a GET request.
|
||||||
|
* If you have a client that sends a non-GET upgrade request, please consider using
|
||||||
|
* {@link #HttpServerUpgradeHandler(SourceCodec, UpgradeCodecFactory, int)} to specify the maximum
|
||||||
|
* length of the content of an upgrade request.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param sourceCodec the codec that is being used initially.
|
* @param sourceCodec the codec that is being used initially
|
||||||
* @param upgradeCodecs the codecs (in order of preference) that this server supports
|
* @param upgradeCodecFactory the factory that creates a new upgrade codec
|
||||||
* upgrading to from the source codec.
|
* for one of the requested upgrade protocols
|
||||||
* @param maxContentLength the maximum length of the aggregated content.
|
|
||||||
*/
|
*/
|
||||||
public HttpServerUpgradeHandler(SourceCodec sourceCodec,
|
public HttpServerUpgradeHandler(SourceCodec sourceCodec, UpgradeCodecFactory upgradeCodecFactory) {
|
||||||
Collection<UpgradeCodec> upgradeCodecs, int maxContentLength) {
|
this(sourceCodec, upgradeCodecFactory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the upgrader with the supported codecs.
|
||||||
|
*
|
||||||
|
* @param sourceCodec the codec that is being used initially
|
||||||
|
* @param upgradeCodecFactory the factory that creates a new upgrade codec
|
||||||
|
* for one of the requested upgrade protocols
|
||||||
|
* @param maxContentLength the maximum length of the content of an upgrade request
|
||||||
|
*/
|
||||||
|
public HttpServerUpgradeHandler(
|
||||||
|
SourceCodec sourceCodec, UpgradeCodecFactory upgradeCodecFactory, int maxContentLength) {
|
||||||
super(maxContentLength);
|
super(maxContentLength);
|
||||||
if (sourceCodec == null) {
|
|
||||||
throw new NullPointerException("sourceCodec");
|
this.sourceCodec = checkNotNull(sourceCodec, "sourceCodec");
|
||||||
}
|
this.upgradeCodecFactory = checkNotNull(upgradeCodecFactory, "upgradeCodecFactory");
|
||||||
if (upgradeCodecs == null) {
|
|
||||||
throw new NullPointerException("upgradeCodecs");
|
|
||||||
}
|
|
||||||
this.sourceCodec = sourceCodec;
|
|
||||||
upgradeCodecMap = new LinkedHashMap<String, UpgradeCodec>(upgradeCodecs.size());
|
|
||||||
for (UpgradeCodec upgradeCodec : upgradeCodecs) {
|
|
||||||
String name = upgradeCodec.protocol().toUpperCase(Locale.US);
|
|
||||||
upgradeCodecMap.put(name, upgradeCodec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -248,8 +262,20 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
*/
|
*/
|
||||||
private boolean upgrade(final ChannelHandlerContext ctx, final FullHttpRequest request) {
|
private boolean upgrade(final ChannelHandlerContext ctx, final FullHttpRequest request) {
|
||||||
// Select the best protocol based on those requested in the UPGRADE header.
|
// Select the best protocol based on those requested in the UPGRADE header.
|
||||||
CharSequence upgradeHeader = request.headers().get(HttpHeaderNames.UPGRADE);
|
final ArrayList<String> requestedProtocols = splitHeader(request.headers().get(HttpHeaderNames.UPGRADE));
|
||||||
final UpgradeCodec upgradeCodec = selectUpgradeCodec(upgradeHeader);
|
final int numRequestedProtocols = requestedProtocols.size();
|
||||||
|
UpgradeCodec upgradeCodec = null;
|
||||||
|
String upgradeProtocol = null;
|
||||||
|
for (int i = 0; i < numRequestedProtocols; i ++) {
|
||||||
|
final String p = requestedProtocols.get(i);
|
||||||
|
final UpgradeCodec c = upgradeCodecFactory.newUpgradeCodec(p);
|
||||||
|
if (c != null) {
|
||||||
|
upgradeProtocol = p;
|
||||||
|
upgradeCodec = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (upgradeCodec == null) {
|
if (upgradeCodec == null) {
|
||||||
// None of the requested protocols are supported, don't upgrade.
|
// None of the requested protocols are supported, don't upgrade.
|
||||||
return false;
|
return false;
|
||||||
@ -263,8 +289,8 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
|
|
||||||
// Make sure the CONNECTION header contains UPGRADE as well as all protocol-specific headers.
|
// Make sure the CONNECTION header contains UPGRADE as well as all protocol-specific headers.
|
||||||
Collection<String> requiredHeaders = upgradeCodec.requiredUpgradeHeaders();
|
Collection<String> requiredHeaders = upgradeCodec.requiredUpgradeHeaders();
|
||||||
Set<CharSequence> values = splitHeader(connectionHeader);
|
List<String> values = splitHeader(connectionHeader);
|
||||||
if (!values.contains(HttpHeaderNames.UPGRADE) || !values.containsAll(requiredHeaders)) {
|
if (!values.contains(UPGRADE_STRING) || !values.containsAll(requiredHeaders)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,12 +302,14 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the user event to be fired once the upgrade completes.
|
// Create the user event to be fired once the upgrade completes.
|
||||||
final UpgradeEvent event = new UpgradeEvent(upgradeCodec.protocol(), request);
|
final UpgradeEvent event = new UpgradeEvent(upgradeProtocol, request);
|
||||||
|
|
||||||
// Prepare and send the upgrade response. Wait for this write to complete before upgrading,
|
// Prepare and send the upgrade response. Wait for this write to complete before upgrading,
|
||||||
// since we need the old codec in-place to properly encode the response.
|
// since we need the old codec in-place to properly encode the response.
|
||||||
final FullHttpResponse upgradeResponse = createUpgradeResponse(upgradeCodec);
|
final FullHttpResponse upgradeResponse = createUpgradeResponse(upgradeProtocol);
|
||||||
upgradeCodec.prepareUpgradeResponse(ctx, request, upgradeResponse);
|
upgradeCodec.prepareUpgradeResponse(ctx, request, upgradeResponse);
|
||||||
|
|
||||||
|
final UpgradeCodec finalUpgradeCodec = upgradeCodec;
|
||||||
ctx.writeAndFlush(upgradeResponse).addListener(new ChannelFutureListener() {
|
ctx.writeAndFlush(upgradeResponse).addListener(new ChannelFutureListener() {
|
||||||
@Override
|
@Override
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
public void operationComplete(ChannelFuture future) throws Exception {
|
||||||
@ -289,7 +317,7 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
if (future.isSuccess()) {
|
if (future.isSuccess()) {
|
||||||
// Perform the upgrade to the new protocol.
|
// Perform the upgrade to the new protocol.
|
||||||
sourceCodec.upgradeFrom(ctx);
|
sourceCodec.upgradeFrom(ctx);
|
||||||
upgradeCodec.upgradeTo(ctx, request, upgradeResponse);
|
finalUpgradeCodec.upgradeTo(ctx, request, upgradeResponse);
|
||||||
|
|
||||||
// Notify that the upgrade has occurred. Retain the event to offset
|
// Notify that the upgrade has occurred. Retain the event to offset
|
||||||
// the release() in the finally block.
|
// the release() in the finally block.
|
||||||
@ -309,33 +337,13 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks up the most desirable supported upgrade codec from the list of choices in the UPGRADE
|
|
||||||
* header. If no suitable codec was found, returns {@code null}.
|
|
||||||
*/
|
|
||||||
private UpgradeCodec selectUpgradeCodec(CharSequence upgradeHeader) {
|
|
||||||
Set<CharSequence> requestedProtocols = splitHeader(upgradeHeader);
|
|
||||||
|
|
||||||
// Retain only the protocols that are in the protocol map. Maintain the original insertion
|
|
||||||
// order into the protocolMap, so that the first one in the remaining set is the most
|
|
||||||
// desirable protocol for the server.
|
|
||||||
Set<String> supportedProtocols = new LinkedHashSet<String>(upgradeCodecMap.keySet());
|
|
||||||
supportedProtocols.retainAll(requestedProtocols);
|
|
||||||
|
|
||||||
if (!supportedProtocols.isEmpty()) {
|
|
||||||
String protocol = supportedProtocols.iterator().next().toUpperCase(Locale.US);
|
|
||||||
return upgradeCodecMap.get(protocol);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the 101 Switching Protocols response message.
|
* Creates the 101 Switching Protocols response message.
|
||||||
*/
|
*/
|
||||||
private static FullHttpResponse createUpgradeResponse(UpgradeCodec upgradeCodec) {
|
private static FullHttpResponse createUpgradeResponse(String upgradeProtocol) {
|
||||||
DefaultFullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, SWITCHING_PROTOCOLS);
|
DefaultFullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, SWITCHING_PROTOCOLS);
|
||||||
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
|
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
|
||||||
res.headers().add(HttpHeaderNames.UPGRADE, upgradeCodec.protocol());
|
res.headers().add(HttpHeaderNames.UPGRADE, upgradeProtocol);
|
||||||
res.headers().add(HttpHeaderNames.CONTENT_LENGTH, "0");
|
res.headers().add(HttpHeaderNames.CONTENT_LENGTH, "0");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -344,9 +352,9 @@ public class HttpServerUpgradeHandler extends HttpObjectAggregator {
|
|||||||
* Splits a comma-separated header value. The returned set is case-insensitive and contains each
|
* Splits a comma-separated header value. The returned set is case-insensitive and contains each
|
||||||
* part with whitespace removed.
|
* part with whitespace removed.
|
||||||
*/
|
*/
|
||||||
private static Set<CharSequence> splitHeader(CharSequence header) {
|
private static ArrayList<String> splitHeader(CharSequence header) {
|
||||||
StringBuilder builder = new StringBuilder(header.length());
|
final StringBuilder builder = new StringBuilder(header.length());
|
||||||
Set<CharSequence> protocols = new TreeSet<CharSequence>(AsciiString.CHARSEQUENCE_CASE_INSENSITIVE_ORDER);
|
final ArrayList<String> protocols = new ArrayList<String>(4);
|
||||||
for (int i = 0; i < header.length(); ++i) {
|
for (int i = 0; i < header.length(); ++i) {
|
||||||
char c = header.charAt(i);
|
char c = header.charAt(i);
|
||||||
if (Character.isWhitespace(c)) {
|
if (Character.isWhitespace(c)) {
|
||||||
|
@ -31,7 +31,6 @@ import java.util.List;
|
|||||||
import static io.netty.handler.codec.base64.Base64Dialect.URL_SAFE;
|
import static io.netty.handler.codec.base64.Base64Dialect.URL_SAFE;
|
||||||
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
|
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.FRAME_HEADER_LENGTH;
|
import static io.netty.handler.codec.http2.Http2CodecUtil.FRAME_HEADER_LENGTH;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME;
|
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.HTTP_UPGRADE_SETTINGS_HEADER;
|
import static io.netty.handler.codec.http2.Http2CodecUtil.HTTP_UPGRADE_SETTINGS_HEADER;
|
||||||
import static io.netty.handler.codec.http2.Http2CodecUtil.writeFrameHeader;
|
import static io.netty.handler.codec.http2.Http2CodecUtil.writeFrameHeader;
|
||||||
import static io.netty.handler.codec.http2.Http2FrameTypes.SETTINGS;
|
import static io.netty.handler.codec.http2.Http2FrameTypes.SETTINGS;
|
||||||
@ -72,11 +71,6 @@ public class Http2ServerUpgradeCodec implements HttpServerUpgradeHandler.Upgrade
|
|||||||
frameReader = new DefaultHttp2FrameReader();
|
frameReader = new DefaultHttp2FrameReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String protocol() {
|
|
||||||
return HTTP_UPGRADE_PROTOCOL_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> requiredUpgradeHeaders() {
|
public Collection<String> requiredUpgradeHeaders() {
|
||||||
return REQUIRED_UPGRADE_HEADERS;
|
return REQUIRED_UPGRADE_HEADERS;
|
||||||
|
@ -19,21 +19,35 @@ package io.netty.example.http2.helloworld.server;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpMessage;
|
import io.netty.handler.codec.http.HttpMessage;
|
||||||
import io.netty.handler.codec.http.HttpServerCodec;
|
import io.netty.handler.codec.http.HttpServerCodec;
|
||||||
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
|
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
|
||||||
|
import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodec;
|
||||||
|
import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodecFactory;
|
||||||
|
import io.netty.handler.codec.http2.Http2CodecUtil;
|
||||||
import io.netty.handler.codec.http2.Http2ServerUpgradeCodec;
|
import io.netty.handler.codec.http2.Http2ServerUpgradeCodec;
|
||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the Netty pipeline for the example server. Depending on the endpoint config, sets up the
|
* Sets up the Netty pipeline for the example server. Depending on the endpoint config, sets up the
|
||||||
* pipeline for NPN or cleartext HTTP upgrade to HTTP/2.
|
* pipeline for NPN or cleartext HTTP upgrade to HTTP/2.
|
||||||
*/
|
*/
|
||||||
public class Http2ServerInitializer extends ChannelInitializer<SocketChannel> {
|
public class Http2ServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
|
|
||||||
|
private static final UpgradeCodecFactory upgradeCodecFactory = new UpgradeCodecFactory() {
|
||||||
|
@Override
|
||||||
|
public UpgradeCodec newUpgradeCodec(String protocol) {
|
||||||
|
if (Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME.equals(protocol)) {
|
||||||
|
return new Http2ServerUpgradeCodec(new HelloWorldHttp2Handler());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final SslContext sslCtx;
|
private final SslContext sslCtx;
|
||||||
|
|
||||||
public Http2ServerInitializer(SslContext sslCtx) {
|
public Http2ServerInitializer(SslContext sslCtx) {
|
||||||
@ -60,25 +74,23 @@ public class Http2ServerInitializer extends ChannelInitializer<SocketChannel> {
|
|||||||
* Configure the pipeline for a cleartext upgrade from HTTP to HTTP/2.
|
* Configure the pipeline for a cleartext upgrade from HTTP to HTTP/2.
|
||||||
*/
|
*/
|
||||||
private static void configureClearText(SocketChannel ch) {
|
private static void configureClearText(SocketChannel ch) {
|
||||||
HttpServerCodec sourceCodec = new HttpServerCodec();
|
final ChannelPipeline p = ch.pipeline();
|
||||||
HttpServerUpgradeHandler.UpgradeCodec upgradeCodec =
|
final HttpServerCodec sourceCodec = new HttpServerCodec();
|
||||||
new Http2ServerUpgradeCodec(new HelloWorldHttp2Handler());
|
|
||||||
HttpServerUpgradeHandler upgradeHandler =
|
|
||||||
new HttpServerUpgradeHandler(sourceCodec, Collections.singletonList(upgradeCodec), 65536);
|
|
||||||
|
|
||||||
ch.pipeline().addLast(sourceCodec);
|
p.addLast(sourceCodec);
|
||||||
ch.pipeline().addLast(upgradeHandler);
|
p.addLast(new HttpServerUpgradeHandler(sourceCodec, upgradeCodecFactory));
|
||||||
ch.pipeline().addLast(new SimpleChannelInboundHandler<HttpMessage>() {
|
p.addLast(new SimpleChannelInboundHandler<HttpMessage>() {
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, HttpMessage msg) throws Exception {
|
protected void channelRead0(ChannelHandlerContext ctx, HttpMessage msg) throws Exception {
|
||||||
// If this handler is hit then no upgrade has been attempted and the client is just talking HTTP.
|
// If this handler is hit then no upgrade has been attempted and the client is just talking HTTP.
|
||||||
System.err.println("Directly talking: " + msg.protocolVersion() + " (no upgrade was attempted)");
|
System.err.println("Directly talking: " + msg.protocolVersion() + " (no upgrade was attempted)");
|
||||||
ctx.pipeline().replace(this, "http-hello-world",
|
ctx.pipeline().replace(this, "http-hello-world",
|
||||||
new HelloWorldHttp1Handler("Direct. No Upgrade Attempted."));
|
new HelloWorldHttp1Handler("Direct. No Upgrade Attempted."));
|
||||||
ctx.fireChannelRead(msg);
|
ctx.fireChannelRead(msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ch.pipeline().addLast(new UserEventLogger());
|
|
||||||
|
p.addLast(new UserEventLogger());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user