Repository: netty/netty
Issue: HTTP/2 examples doesn't work with Chrome 42.0.2311.135 (64-bit) on OSX 10.10.3 , Java  1.8.0_45-b14 , Netty 5.0.0.Alpha3-SNAPSHOT 
Labels: defect

The request stays as "pending"  forever

![image](https://cloud.githubusercontent.com/assets/927575/7539825/5457c9ba-f5b2-11e4-96d0-a5620b54ef8b.png)

The debug output:
May 08, 2015 6:45:27 PM io.netty.handler.logging.LoggingHandler channelRead
INFO: [id: 0x4d9163c8, /0:0:0:0:0:0:0:0:8080] RECEIVED: [id: 0x2e91accb, /127.0.0.1:64231 => /127.0.0.1:8080]

---

But the http2 client that is provided in the examples works flawlessly.

Hello World
---Stream id: 3 received---
Finished HTTP/2 request(s)


Issue comments:
@bobymicroby - Thanks for reaching out!

What flags are you starting chrome with?  Are you starting the example with the `-Dssl` flag?  What version of netty are you using?

@Scottmitch it's @bobymicroby ;)

In order for the example to work with chrome you will have to change Netty's http2 ALPN token from [h2-17](https://github.com/netty/netty/blob/master/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2CodecUtil.java#L39) to `h2-14`.

@Scottmitch No ssl,  the netty build is from master. I was expecting that Http2OrHttpHandler to select http 1 protocol if unable to upgrade.  Where do  you suggest me to implement the  fallback logic ?  

@bobymicroby - I observe the same behavior without `-Dssl` option when starting the `http2-server` example. However with the `-Dssl` option I am able to negotiate to `HTTP_1_1` (if I change nothing) and able to negotiate to `HTTP_2` (if I change the version to `h2-14`).  I'm not sure that chrome or firefox support clear text mode for HTTP/2.  I think the reason why you are seeing the client example work is because we do support clear text mode.

@Scottmitch Don't you think its best always to revert to http 1 if you cannot negotiate 2 ? 

@bobymicroby - Good point. Even though the example is to demonstrate HTTP/2 functionality I guess we should send some kind of response for http only clients.  I'll put together a PR.

@Scottmitch Something like  " Hello old world. I was unable to negotiate a good protocol upgrade, but at least your request got served "   :) 

@bobymicroby - See #3793 

Fixed 4.1 (04c0d77, c6d61f9) master(37e6fd0)


Pull request review comments:

Patch that resolved the issue:
diff --git a/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp1Handler.java b/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp1Handler.java
index 009e8fa2131..aa8f1d29494 100644
--- a/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp1Handler.java
+++ b/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp1Handler.java
@@ -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;
@@ -24,7 +26,6 @@
 import io.netty.handler.codec.http.HttpHeaderUtil;
 import io.netty.handler.codec.http.HttpHeaderValues;
 import io.netty.handler.codec.http.HttpRequest;
-
 import static io.netty.handler.codec.http.HttpHeaderNames.*;
 import static io.netty.handler.codec.http.HttpResponseStatus.*;
 import static io.netty.handler.codec.http.HttpVersion.*;
@@ -33,6 +34,11 @@
  * 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 messageReceived(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
@@ -43,6 +49,7 @@ public void messageReceived(ChannelHandlerContext ctx, HttpRequest req) throws E
 
         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");
diff --git a/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java b/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java
index 61fff9e4b91..f0ae73fd6e1 100644
--- a/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java
+++ b/example/src/main/java/io/netty/example/http2/server/HelloWorldHttp2Handler.java
@@ -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;
@@ -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);
             }
         }
 
diff --git a/example/src/main/java/io/netty/example/http2/server/Http2OrHttpHandler.java b/example/src/main/java/io/netty/example/http2/server/Http2OrHttpHandler.java
index bb8cae84f86..e07dec24868 100644
--- a/example/src/main/java/io/netty/example/http2/server/Http2OrHttpHandler.java
+++ b/example/src/main/java/io/netty/example/http2/server/Http2OrHttpHandler.java
@@ -48,7 +48,7 @@ protected SelectedProtocol getProtocol(SSLEngine engine) {
 
     @Override
     protected ChannelHandler createHttp1RequestHandler() {
-        return new HelloWorldHttp1Handler();
+        return new HelloWorldHttp1Handler("ALPN Negotiation");
     }
 
     @Override
diff --git a/example/src/main/java/io/netty/example/http2/server/Http2ServerInitializer.java b/example/src/main/java/io/netty/example/http2/server/Http2ServerInitializer.java
index ac36a9819b4..cc5a7f31ada 100644
--- a/example/src/main/java/io/netty/example/http2/server/Http2ServerInitializer.java
+++ b/example/src/main/java/io/netty/example/http2/server/Http2ServerInitializer.java
@@ -19,7 +19,9 @@
 import io.netty.channel.ChannelHandlerAdapter;
 import io.netty.channel.ChannelHandlerContext;
 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;
@@ -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());
     }
 


Test patch: