in servicetalk-http-netty/src/main/java/io/servicetalk/http/netty/H2ToStH1Utils.java [109:187]
static Http2Headers h1HeadersToH2Headers(HttpHeaders h1Headers) {
if (h1Headers.isEmpty()) {
if (h1Headers instanceof NettyH2HeadersToHttpHeaders) {
return ((NettyH2HeadersToHttpHeaders) h1Headers).nettyHeaders();
}
return new DefaultHttp2Headers(false, 0);
}
// H2 doesn't support connection headers, so remove each one, and the headers corresponding to the
// connection value.
// https://tools.ietf.org/html/rfc7540#section-8.1.2.2
Iterator<? extends CharSequence> connectionItr = h1Headers.valuesIterator(CONNECTION);
if (connectionItr.hasNext()) {
do {
String connectionHeader = connectionItr.next().toString();
connectionItr.remove();
int i = connectionHeader.indexOf(',');
if (i != -1) {
int start = 0;
do {
h1Headers.remove(connectionHeader.substring(start, i));
start = i + 1;
} while (start < connectionHeader.length() && (i = connectionHeader.indexOf(',', start)) != -1);
h1Headers.remove(connectionHeader.substring(start));
} else {
h1Headers.remove(connectionHeader);
}
} while (connectionItr.hasNext());
}
// remove other illegal headers
h1Headers.remove(KEEP_ALIVE);
h1Headers.remove(TRANSFER_ENCODING);
h1Headers.remove(UPGRADE);
// TE header is treated specially https://tools.ietf.org/html/rfc7540#section-8.1.2.2
// (only value of "trailers" is allowed).
Iterator<? extends CharSequence> teItr = h1Headers.valuesIterator(TE);
boolean addTrailers = false;
while (teItr.hasNext()) {
String teValue = teItr.next().toString();
int i = teValue.indexOf(',');
if (i != -1) {
int start = 0;
do {
if (teValue.substring(start, i).compareToIgnoreCase(TRAILERS.toString()) == 0) {
addTrailers = true;
break;
}
} while (start < teValue.length() && (i = teValue.indexOf(',', start)) != -1);
teItr.remove();
} else if (teValue.compareToIgnoreCase(TRAILERS.toString()) != 0) {
teItr.remove();
}
}
if (addTrailers) { // add after iteration to avoid concurrent modification.
h1Headers.add(TE, TRAILERS);
}
h1HeadersSplitCookieCrumbs(h1Headers);
if (h1Headers instanceof NettyH2HeadersToHttpHeaders) {
// Assume header field names are already lowercase if they reside in the Http2Headers. We may want to be
// more strict in the future, but that would require iteration.
return ((NettyH2HeadersToHttpHeaders) h1Headers).nettyHeaders();
}
if (h1Headers.isEmpty()) {
return new DefaultHttp2Headers(false, 0);
}
DefaultHttp2Headers http2Headers = new DefaultHttp2Headers(false);
for (Map.Entry<CharSequence, CharSequence> h1Entry : h1Headers) {
// header field names MUST be converted to lowercase prior to their encoding in HTTP/2
// https://tools.ietf.org/html/rfc7540#section-8.1.2
http2Headers.add(h1Entry.getKey().toString().toLowerCase(), h1Entry.getValue());
}
return http2Headers;
}