Only enable validation of headers if original headers were validating as well.

Motiviation:

In our replace(...) methods we always used validation for the newly created headers while the original headers may not use validation at all.

Modifications:

- Only use validation if the original headers used validation as well.
- Ensure we create a copy of the headers in replace(...).

Result:

Fixes [#5226]
This commit is contained in:
Norman Maurer 2017-12-13 20:26:35 +01:00
parent 144716f668
commit 942b993f2b
7 changed files with 38 additions and 8 deletions

View File

@ -142,7 +142,10 @@ public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHt
@Override @Override
public FullHttpRequest replace(ByteBuf content) { public FullHttpRequest replace(ByteBuf content) {
return new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content, headers(), trailingHeaders()); FullHttpRequest request = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content,
headers().copy(), trailingHeaders().copy());
request.setDecoderResult(decoderResult());
return request;
} }
@Override @Override

View File

@ -149,7 +149,10 @@ public class DefaultFullHttpResponse extends DefaultHttpResponse implements Full
@Override @Override
public FullHttpResponse replace(ByteBuf content) { public FullHttpResponse replace(ByteBuf content) {
return new DefaultFullHttpResponse(protocolVersion(), status(), content, headers(), trailingHeaders()); FullHttpResponse response = new DefaultFullHttpResponse(protocolVersion(), status(), content,
headers().copy(), trailingHeaders().copy());
response.setDecoderResult(decoderResult());
return response;
} }
@Override @Override

View File

@ -348,6 +348,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
return headers.hashCode(CASE_SENSITIVE_HASHER); return headers.hashCode(CASE_SENSITIVE_HASHER);
} }
@Override
public HttpHeaders copy() {
return new DefaultHttpHeaders(headers.copy());
}
private static void validateHeaderNameElement(byte value) { private static void validateHeaderNameElement(byte value) {
switch (value) { switch (value) {
case 0x00: case 0x00:

View File

@ -1693,4 +1693,11 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
public String toString() { public String toString() {
return HeadersUtils.toString(getClass(), iteratorCharSequence(), size()); return HeadersUtils.toString(getClass(), iteratorCharSequence(), size());
} }
/**
* Returns a deap copy of the passed in {@link HttpHeaders}.
*/
public HttpHeaders copy() {
return new DefaultHttpHeaders().set(this);
}
} }

View File

@ -424,9 +424,8 @@ public class HttpObjectAggregator
@Override @Override
public FullHttpRequest replace(ByteBuf content) { public FullHttpRequest replace(ByteBuf content) {
DefaultFullHttpRequest dup = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content); DefaultFullHttpRequest dup = new DefaultFullHttpRequest(protocolVersion(), method(), uri(), content,
dup.headers().set(headers()); headers().copy(), trailingHeaders().copy());
dup.trailingHeaders().set(trailingHeaders());
dup.setDecoderResult(decoderResult()); dup.setDecoderResult(decoderResult());
return dup; return dup;
} }
@ -523,9 +522,8 @@ public class HttpObjectAggregator
@Override @Override
public FullHttpResponse replace(ByteBuf content) { public FullHttpResponse replace(ByteBuf content) {
DefaultFullHttpResponse dup = new DefaultFullHttpResponse(getProtocolVersion(), getStatus(), content); DefaultFullHttpResponse dup = new DefaultFullHttpResponse(getProtocolVersion(), getStatus(), content,
dup.headers().set(headers()); headers().copy(), trailingHeaders().copy());
dup.trailingHeaders().set(trailingHeaders());
dup.setDecoderResult(decoderResult()); dup.setDecoderResult(decoderResult());
return dup; return dup;
} }

View File

@ -62,6 +62,7 @@ import static io.netty.handler.codec.http2.Http2TestUtil.of;
import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel; import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@ -607,6 +608,9 @@ public class InboundHttp2ToHttpAdapterTest {
verify(serverListener, times(2)).messageReceived(requestCaptor.capture()); verify(serverListener, times(2)).messageReceived(requestCaptor.capture());
capturedRequests = requestCaptor.getAllValues(); capturedRequests = requestCaptor.getAllValues();
assertEquals(2, capturedRequests.size()); assertEquals(2, capturedRequests.size());
// We do not expect to have this header in the captured request so remove it now.
assertNotNull(request.headers().remove("x-http2-stream-weight"));
assertEquals(request, capturedRequests.get(0)); assertEquals(request, capturedRequests.get(0));
assertEquals(request2, capturedRequests.get(1)); assertEquals(request2, capturedRequests.get(1));

View File

@ -952,6 +952,16 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
return (T) this; return (T) this;
} }
/**
* Returns a deep copy of this instance.
*/
public DefaultHeaders<K, V, T> copy() {
DefaultHeaders<K, V, T> copy = new DefaultHeaders<K, V, T>(
hashingStrategy, valueConverter, nameValidator, entries.length);
copy.addImpl(this);
return copy;
}
private final class HeaderIterator implements Iterator<Map.Entry<K, V>> { private final class HeaderIterator implements Iterator<Map.Entry<K, V>> {
private HeaderEntry<K, V> current = head; private HeaderEntry<K, V> current = head;