Issue #5104 - AbstractProxyServlet include incorrect protocol version in Via header when accessed over H2.

Added HttpFields.computeField() for HttpHeader too and updated usages.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Simone Bordet 2020-08-13 11:50:43 +02:00
parent c3598e814b
commit 7b3dccc1bf
4 changed files with 27 additions and 10 deletions

View File

@ -90,7 +90,7 @@ public class HttpFields implements Iterable<HttpField>
}
/**
* <p>Computes a single field for the given HTTP header name and for existing fields with the same name.</p>
* <p>Computes a single field for the given HttpHeader and for existing fields with the same header.</p>
*
* <p>The compute function receives the field name and a list of fields with the same name
* so that their values can be used to compute the value of the field that is returned
@ -161,17 +161,34 @@ public class HttpFields implements Iterable<HttpField>
* httpFields.computeField("Connection", (name, fields) -&gt; null);
* </pre>
*
* @param name the HTTP header name
* @param header the HTTP header
* @param computeFn the compute function
*/
public void computeField(HttpHeader header, BiFunction<HttpHeader, List<HttpField>, HttpField> computeFn)
{
computeField(header, computeFn, (f, h) -> f.getHeader() == h);
}
/**
* <p>Computes a single field for the given HTTP header name and for existing fields with the same name.</p>
*
* @param name the HTTP header name
* @param computeFn the compute function
* @see #computeField(HttpHeader, BiFunction)
*/
public void computeField(String name, BiFunction<String, List<HttpField>, HttpField> computeFn)
{
computeField(name, computeFn, HttpField::is);
}
private <T> void computeField(T header, BiFunction<T, List<HttpField>, HttpField> computeFn, BiFunction<HttpField, T, Boolean> matcher)
{
// Look for first occurrence
int first = -1;
for (int i = 0; i < _size; i++)
{
HttpField f = _fields[i];
if (f.is(name))
if (matcher.apply(f, header))
{
first = i;
break;
@ -181,7 +198,7 @@ public class HttpFields implements Iterable<HttpField>
// If the header is not found, add a new one;
if (first < 0)
{
HttpField newField = computeFn.apply(name, null);
HttpField newField = computeFn.apply(header, null);
if (newField != null)
add(newField);
return;
@ -192,7 +209,7 @@ public class HttpFields implements Iterable<HttpField>
for (int i = first + 1; i < _size; i++)
{
HttpField f = _fields[i];
if (f.is(name))
if (matcher.apply(f, header))
{
if (found == null)
{
@ -211,7 +228,7 @@ public class HttpFields implements Iterable<HttpField>
else
found = Collections.unmodifiableList(found);
HttpField newField = computeFn.apply(name, found);
HttpField newField = computeFn.apply(header, found);
if (newField == null)
remove(first);
else

View File

@ -868,7 +868,7 @@ public class HttpFieldsTest
}
@Test
public void testCompute()
public void testComputeField()
{
HttpFields header = new HttpFields();
assertThat(header.size(), is(0));

View File

@ -554,10 +554,10 @@ public abstract class AbstractProxyServlet extends HttpServlet
// Retain only the version if the protocol is HTTP.
String protocolPart = parts.length == 2 && "HTTP".equalsIgnoreCase(parts[0]) ? parts[1] : protocol;
String viaHeaderValue = protocolPart + " " + getViaHost();
proxyRequest.getHeaders().computeField(HttpHeader.VIA.asString(), (name, viaFields) ->
proxyRequest.getHeaders().computeField(HttpHeader.VIA, (header, viaFields) ->
{
if (viaFields == null || viaFields.isEmpty())
return new HttpField(name, viaHeaderValue);
return new HttpField(header, viaHeaderValue);
String separator = ", ";
String newValue = viaFields.stream()
.flatMap(field -> Stream.of(field.getValues()))

View File

@ -662,7 +662,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
baseRequest.getHttpFields().computeField(HttpHeader.CONTENT_LENGTH.asString(), (name, fields) ->
baseRequest.getHttpFields().computeField(HttpHeader.CONTENT_LENGTH, (header, fields) ->
{
if (fields == null)
return null;