From fbda9a07997c443203b1a7802f7ac5abe5c238ca Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 12 Mar 2019 11:26:09 +1100 Subject: [PATCH] Issue #3444 Preencoded unknown field Signed-off-by: Greg Wilkins --- .../jetty/http/Http1FieldPreEncoder.java | 7 ++++--- .../jetty/http/PreEncodedHttpField.java | 3 +-- .../org/eclipse/jetty/http/HttpFieldsTest.java | 18 ++++++++++++++++++ .../HttpConfigurationCustomizerTest.java | 8 ++++---- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/Http1FieldPreEncoder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/Http1FieldPreEncoder.java index c94ebffdbf5..17da781202e 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/Http1FieldPreEncoder.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/Http1FieldPreEncoder.java @@ -19,10 +19,10 @@ package org.eclipse.jetty.http; -import static java.nio.charset.StandardCharsets.ISO_8859_1; - import java.util.Arrays; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + /* ------------------------------------------------------------ */ /** @@ -60,7 +60,8 @@ public class Http1FieldPreEncoder implements HttpFieldPreEncoder byte[] v=value.getBytes(ISO_8859_1); byte[] bytes=Arrays.copyOf(n,n.length+2+v.length+2); bytes[n.length]=(byte)':'; - bytes[n.length]=(byte)' '; + bytes[n.length+1]=(byte)' '; + System.arraycopy(v, 0, bytes, n.length+2, v.length); bytes[bytes.length-2]=(byte)'\r'; bytes[bytes.length-1]=(byte)'\n'; diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/PreEncodedHttpField.java b/jetty-http/src/main/java/org/eclipse/jetty/http/PreEncodedHttpField.java index 11ad88821c0..7b5c0c47d88 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/PreEncodedHttpField.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/PreEncodedHttpField.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.http; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; @@ -73,7 +72,7 @@ public class PreEncodedHttpField extends HttpField else LOG.warn("multiple PreEncoders for "+e.getHttpVersion()); } - + // Always support HTTP1 if (__encoders[0]==null) __encoders[0] = new Http1FieldPreEncoder(); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java index dc6f4a9e6ec..258eb766df8 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java @@ -299,6 +299,24 @@ public class HttpFieldsTest assertEquals(false, e.hasMoreElements()); } + @Test + public void testPreEncodedField() + { + ByteBuffer buffer = BufferUtil.allocate(1024); + + PreEncodedHttpField known = new PreEncodedHttpField(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()); + BufferUtil.clearToFill(buffer); + known.putTo(buffer,HttpVersion.HTTP_1_1); + BufferUtil.flipToFlush(buffer,0); + assertThat(BufferUtil.toString(buffer),is("Connection: close\r\n")); + + PreEncodedHttpField unknown = new PreEncodedHttpField(null, "Header", "Value"); + BufferUtil.clearToFill(buffer); + unknown.putTo(buffer,HttpVersion.HTTP_1_1); + BufferUtil.flipToFlush(buffer,0); + assertThat(BufferUtil.toString(buffer),is("Header: Value\r\n")); + } + @Test public void testAddPreEncodedField() { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationCustomizerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationCustomizerTest.java index b8747bd40ac..6afa954cd86 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationCustomizerTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConfigurationCustomizerTest.java @@ -19,12 +19,13 @@ package org.eclipse.jetty.server; import java.io.IOException; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpTester; +import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler; import org.junit.jupiter.api.AfterEach; @@ -49,10 +50,10 @@ public class HttpConfigurationCustomizerTest http.getHttpConfiguration().setSecurePort(9999); http.getHttpConfiguration().setSecureScheme("https"); + final PreEncodedHttpField X_XSS_PROTECTION_FIELD = new PreEncodedHttpField("X-XSS-Protection", "1; mode=block"); + HttpConnectionFactory https = new HttpConnectionFactory(http.getHttpConfiguration()); https.getHttpConfiguration().addCustomizer((connector, channelConfig, request) -> { - // INVALID: final PreEncodedHttpField X_XSS_PROTECTION_FIELD = new PreEncodedHttpField("X-XSS-Protection", "1; mode=block"); - final HttpField X_XSS_PROTECTION_FIELD = new HttpField("X-XSS-Protection", "1; mode=block"); request.setScheme(HttpScheme.HTTPS.asString()); request.setSecure(true); request.getResponse().getHttpFields().add(X_XSS_PROTECTION_FIELD); // test response header @@ -94,7 +95,6 @@ public class HttpConfigurationCustomizerTest "\r\n"; String rawResponse = localConnector.getResponse(request); - System.out.println(rawResponse); HttpTester.Response response = HttpTester.parseResponse(rawResponse); assertThat("Response status", response.getStatus(), is(200)); assertThat("Response body", response.getContent(), containsString("Success"));