Repository: netty/netty
File: codec-http2/src/main/java/io/netty/handler/codec/http2/HttpConversionUtil.java (Java)

Code before:
                }
            }
        }
    }

    public static void toHttp2Headers(HttpHeaders inHeaders, Http2Headers out) {
        Iterator<Entry<CharSequence, CharSequence>> iter = inHeaders.iteratorCharSequence();
        // Choose 8 as a default size because it is unlikely we will see more than 4 Connection headers values, but
        // still allowing for "enough" space in the map to reduce the chance of hash code collision.
        CharSequenceMap<AsciiString> connectionBlacklist =
            toLowercaseMap(inHeaders.valueCharSequenceIterator(CONNECTION), 8);
        while (iter.hasNext()) {
            Entry<CharSequence, CharSequence> entry = iter.next();
            final AsciiString aName = AsciiString.of(entry.getKey()).toLowerCase();
            if (!HTTP_TO_HTTP2_HEADER_BLACKLIST.contains(aName) && !connectionBlacklist.contains(aName)) {
                // https://tools.ietf.org/html/rfc7540#section-8.1.2.2 makes a special exception for TE
                if (aName.contentEqualsIgnoreCase(TE)) {
                    toHttp2HeadersFilterTE(entry, out);
                } else if (aName.contentEqualsIgnoreCase(COOKIE)) {
                    CharSequence valueCs = entry.getValue();
                    try {
                        // validate
                        boolean invalid = false;
                        for (int i = 0; i < valueCs.length(); i++) {
                            char c = valueCs.charAt(i);
                            if (c == ';') {
                                if (i + 1 >= valueCs.length() || valueCs.charAt(i + 1) != ' ') {
                                    invalid = true;
                                    break;
                                }
                                i++; // skip space
                            } else if (c > 255) {
                                // not ascii, don't split
                                invalid = true;
                                break;
                            }
                        }

                        if (invalid) {
                            out.add(COOKIE, valueCs);
                        } else {
                            AsciiString value = AsciiString.of(valueCs);
                            // split up cookies to allow for better compression
                            // https://tools.ietf.org/html/rfc7540#section-8.1.2.5
                            int index = value.forEachByte(FIND_SEMI_COLON);
                            if (index != -1) {
                                int start = 0;
                                do {
                                    out.add(COOKIE, value.subSequence(start, index, false));
                                    assert index + 1 < value.length();
                                    assert value.charAt(index + 1) == ' ';

Review comment (suggestion):
Feel free to ignore: it was this way when you found it, but if you end up making another commit it might be nice to lift all this out into its own method to isolate the noise. There is already precedent in `toHttp2HeadersFilterTE`.

Code after:
                }
            }
        }
    }

    public static void toHttp2Headers(HttpHeaders inHeaders, Http2Headers out) {
        Iterator<Entry<CharSequence, CharSequence>> iter = inHeaders.iteratorCharSequence();
        // Choose 8 as a default size because it is unlikely we will see more than 4 Connection headers values, but
        // still allowing for "enough" space in the map to reduce the chance of hash code collision.
        CharSequenceMap<AsciiString> connectionBlacklist =
            toLowercaseMap(inHeaders.valueCharSequenceIterator(CONNECTION), 8);
        while (iter.hasNext()) {
            Entry<CharSequence, CharSequence> entry = iter.next();
            final AsciiString aName = AsciiString.of(entry.getKey()).toLowerCase();
            if (!HTTP_TO_HTTP2_HEADER_BLACKLIST.contains(aName) && !connectionBlacklist.contains(aName)) {
                // https://tools.ietf.org/html/rfc7540#section-8.1.2.2 makes a special exception for TE
                if (aName.contentEqualsIgnoreCase(TE)) {
                    toHttp2HeadersFilterTE(entry, out);
                } else if (aName.contentEqualsIgnoreCase(COOKIE)) {
                    CharSequence valueCs = entry.getValue();
                    // validate
                    boolean invalid = false;
                    for (int i = 0; i < valueCs.length(); i++) {
                        char c = valueCs.charAt(i);
                        if (c == ';') {
                            if (i + 1 >= valueCs.length() || valueCs.charAt(i + 1) != ' ') {
                                // semicolon not followed by space. invalid, don't split
                                invalid = true;
                                break;
                            }
                            i++; // skip space
                        } else if (c > 255) {
                            // not ascii, don't split
                            invalid = true;
                            break;
                        }
                    }

                    if (invalid) {
                        out.add(COOKIE, valueCs);
                    } else {
                        splitValidCookieHeader(out, valueCs);
                    }
                } else {
                    out.add(aName, entry.getValue());
                }
            }
        }
    }

    private static void splitValidCookieHeader(Http2Headers out, CharSequence valueCs) {