Skip to content

Commit

Permalink
HTTP/2 Server Example No Response for HTTP/1.x Only Clients
Browse files Browse the repository at this point in the history
Motiviation:
The HTTP/2 server example just hangs when a client is using only HTTP with no ALPN or upgrade attempts. We should still send some kind of response.

Modifications:
The HTTP/2 server example has a special handler to detect no upgrade HTTP clients and generate a response.

Result:
Clients that just use HTTP with no upgrade will no appear hung when interacting with the HTTP/2 server example.
  • Loading branch information
Scottmitch committed May 18, 2015
1 parent 9bf6360 commit 04c0d77
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*/
package io.netty.example.http2.server;

import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
Expand All @@ -31,11 +33,15 @@
import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
* HTTP handler that responds with a "Hello World"
*/
public class HelloWorldHttp1Handler extends SimpleChannelInboundHandler<HttpRequest> {
private final String establishApproach;

public HelloWorldHttp1Handler(String establishApproach) {
this.establishApproach = checkNotNull(establishApproach, "establishApproach");
}

@Override
public void channelRead0(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
Expand All @@ -46,6 +52,7 @@ public void channelRead0(ChannelHandlerContext ctx, HttpRequest req) throws Exce

ByteBuf content = ctx.alloc().buffer();
content.writeBytes(HelloWorldHttp2Handler.RESPONSE_BYTES.duplicate());
ByteBufUtil.writeAscii(content, " - via " + req.protocolVersion() + " (" + establishApproach + ")");

FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.logging.LogLevel.INFO;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
import io.netty.handler.codec.http2.DefaultHttp2Connection;
Expand Down Expand Up @@ -112,7 +113,10 @@ public void onHeadersRead(ChannelHandlerContext ctx, int streamId,
Http2Headers headers, int streamDependency, short weight,
boolean exclusive, int padding, boolean endStream) throws Http2Exception {
if (endStream) {
sendResponse(ctx, streamId, RESPONSE_BYTES.duplicate());
ByteBuf content = ctx.alloc().buffer();
content.writeBytes(HelloWorldHttp2Handler.RESPONSE_BYTES.duplicate());
ByteBufUtil.writeAscii(content, " - via HTTP/2");
sendResponse(ctx, streamId, content);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protected SelectedProtocol getProtocol(SSLEngine engine) {

@Override
protected ChannelHandler createHttp1RequestHandler() {
return new HelloWorldHttp1Handler();
return new HelloWorldHttp1Handler("ALPN Negotiation");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpMessage;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
import io.netty.handler.codec.http2.Http2ServerUpgradeCodec;
Expand Down Expand Up @@ -66,6 +68,16 @@ private static void configureClearText(SocketChannel ch) {

ch.pipeline().addLast(sourceCodec);
ch.pipeline().addLast(upgradeHandler);
ch.pipeline().addLast(new SimpleChannelInboundHandler<HttpMessage>() {
@Override
protected void messageReceived(ChannelHandlerContext ctx, HttpMessage msg) throws Exception {
// 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)");
ctx.pipeline().replace(this, "http-hello-world",
new HelloWorldHttp1Handler("Direct. No Upgrade Attempted."));
ctx.fireChannelRead(msg);
}
});
ch.pipeline().addLast(new UserEventLogger());
}

Expand Down

0 comments on commit 04c0d77

Please sign in to comment.