Repository: netty/netty
Issue: Chrome/Firefox send `upgrade-insecure-requests` header

https://github.com/netty/netty/pull/12755 is unfortunately breaking Chrome and Firefox which both (rightly or wrongly) send the `upgrade-insecure-requests` header:

```
[DEBUG|2022-09-13 10:23:29.419|netty-worker1 ||io.netty.handler.codec.http2.Http2FrameCodec] Stream exception thrown for unknown stream 1.
io.netty.handler.codec.http2.Http2Exception$StreamException: Illegal connection-specific header 'upgrade-insecure-requests' encountered.
	at io.netty.handler.codec.http2.Http2Exception.streamError(Http2Exception.java:153)
	at io.netty.handler.codec.http2.HpackDecoder.validate(HpackDecoder.java:412)
	at io.netty.handler.codec.http2.HpackDecoder.access$000(HpackDecoder.java:56)
	at io.netty.handler.codec.http2.HpackDecoder$Http2HeadersSink.appendToHeaderList(HpackDecoder.java:639)
	at io.netty.handler.codec.http2.HpackDecoder.insertHeader(HpackDecoder.java:506)
	at io.netty.handler.codec.http2.HpackDecoder.decode(HpackDecoder.java:294)
	at io.netty.handler.codec.http2.HpackDecoder.decode(HpackDecoder.java:131)
```

With Netty 4.1.80 and below I was able to run with `validateHeaders(true)` (the default). However with Netty 4.1.81 the only work around I've found is;
```
        Http2FrameCodecBuilder builder = Http2FrameCodecBuilder.forServer();
        builder.validateHeaders(false);
```

@chrisvest My thanks for implementing these extra validations. And my thanks too for helping me investigate this. I am running with a particularly restrictive 'Content-Security-Policy' header - but that doesn't seem to be related as the exception above occurs well before a cache-clean web-browser sends the `upgrade-insecure-requests` header.

Issue comments:
Just verified that the validation is fine for Safari but fails with Firefox.

Pull request review comments:

Patch that resolved the issue:
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java
index cf474fce584..9d2bd875be8 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/HpackDecoder.java
@@ -422,13 +422,12 @@ private static HeaderType validate(int streamId, CharSequence name,
 
     @SuppressWarnings("deprecation") // We need to check for deprecated headers as well.
     private static boolean isConnectionHeader(CharSequence name) {
-        // These are the known standard and non-standard connection related headers:
+        // These are the known standard connection related headers:
         // - upgrade (7 chars)
         // - connection (10 chars)
         // - keep-alive (10 chars)
         // - proxy-connection (16 chars)
         // - transfer-encoding (17 chars)
-        // - upgrade-insecure-requests (25 chars)
         //
         // We scan for these based on the length, then double-check any matching name.
         int len = name.length();
@@ -449,7 +448,7 @@ private static boolean isConnectionHeader(CharSequence name) {
         if (len == 16) {
             return contentEqualsIgnoreCase(name, HttpHeaderNames.PROXY_CONNECTION);
         }
-        return len == 25 && contentEqualsIgnoreCase(name, HttpHeaderNames.UPGRADE_INSECURE_REQUESTS);
+        return false;
     }
 
     private static boolean contains(Http2Headers headers, CharSequence name) {


Test patch:
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java
index 1b25fea70fc..ec5c4a23ef6 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java
@@ -167,9 +167,6 @@ public void decodingConnectionRelatedHeadersMustFailValidation() throws Exceptio
 
         // Non-standard connection related headers:
         verifyValidationFails(decoder, encode(b(":method"), b("GET"), b("proxy-connection"), b("keep-alive")));
-        verifyValidationFails(decoder, encode(b(":method"), b("GET"), b("upgrade-insecure-requests"), b("1")));
-        verifyValidationFails(decoder, encode(b(":method"), b("GET"),
-                b("content-security-policy"), b("upgrade-insecure-requests"), b("upgrade-insecure-requests"), b("1")));
 
         // Only "trailers" is allowed for the TE header:
         verifyValidationFails(decoder, encode(b(":method"), b("GET"), b("te"), b("compress")));