Author: markt
Date: Wed Oct 19 13:31:26 2016
New Revision: 1765589
URL: http://svn.apache.org/viewvc?rev=1765589&view=rev
Log:
Add initial support for trailer headers
Modified:
tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
tomcat/trunk/java/org/apache/coyote/http2/Stream.java
tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java
Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed Oct
19 13:31:26 2016
@@ -1247,8 +1247,9 @@ class Http2UpgradeHandler extends Abstra
setMaxProcessedStream(streamId);
Stream stream = getStream(streamId,
connectionState.get().isNewStreamAllowed());
if (stream != null && stream.isActive()) {
- stream.receivedEndOfHeaders();
- processStreamOnContainerThread(stream);
+ if (stream.receivedEndOfHeaders()) {
+ processStreamOnContainerThread(stream);
+ }
}
}
Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed Oct 19 13:31:26
2016
@@ -293,13 +293,14 @@ class Stream extends AbstractStream impl
}
- final void receivedEndOfHeaders() {
+ final boolean receivedEndOfHeaders() {
// Cookie headers need to be concatenated into a single header
// See RFC 7540 8.1.2.5
// Can only do this once the headers are fully received
if (cookieHeader != null) {
coyoteRequest.getMimeHeaders().addValue("cookie").setString(cookieHeader.toString());
}
+ return headerState == HEADER_STATE_REGULAR || headerState ==
HEADER_STATE_PSEUDO;
}
@@ -362,6 +363,9 @@ class Stream extends AbstractStream impl
final void receivedEndOfStream() {
+ synchronized (inputBuffer) {
+ inputBuffer.notifyAll();
+ }
state.recievedEndOfStream();
}
Modified: tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Wed Oct 19
13:31:26 2016
@@ -69,6 +69,8 @@ public abstract class Http2TestBase exte
EMPTY_HTTP2_SETTINGS_HEADER = "HTTP2-Settings: " +
Base64.encodeBase64String(empty) + "\r\n";
}
+ private static final String TRAILER_HEADER_NAME = "X-TrailerTest";
+
private Socket s;
protected HpackEncoder hpackEncoder;
protected Input input;
@@ -294,6 +296,13 @@ public abstract class Http2TestBase exte
protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer
headersPayload,
boolean useExpectation, byte[] dataFrameHeader, ByteBuffer
dataPayload, byte[] padding,
int streamId) {
+ buildPostRequest(headersFrameHeader, headersPayload, useExpectation,
dataFrameHeader,
+ dataPayload, padding, null, null, streamId);
+ }
+
+ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer
headersPayload,
+ boolean useExpectation, byte[] dataFrameHeader, ByteBuffer
dataPayload, byte[] padding,
+ byte[] trailersFrameHeader, ByteBuffer trailersPayload, int
streamId) {
MimeHeaders headers = new MimeHeaders();
headers.addValue(":method").setString("POST");
headers.addValue(":path").setString("/simple");
@@ -332,12 +341,31 @@ public abstract class Http2TestBase exte
ByteUtil.setThreeBytes(dataFrameHeader, 0, dataPayload.limit());
// Data is type 0
// Flags: End of stream 1, Padding 8
- if (padding == null) {
+ if (trailersPayload == null) {
dataFrameHeader[4] = 0x01;
} else {
- dataFrameHeader[4] = 0x09;
+ dataFrameHeader[4] = 0x00;
+ }
+ if (padding != null) {
+ dataFrameHeader[4] += 0x08;
}
ByteUtil.set31Bits(dataFrameHeader, 5, streamId);
+
+ // Trailers
+ if (trailersPayload != null) {
+ MimeHeaders trailerHeaders = new MimeHeaders();
+ trailerHeaders.addValue(TRAILER_HEADER_NAME).setString("xxxx");
+ hpackEncoder.encode(trailerHeaders, trailersPayload);
+
+ trailersPayload.flip();
+
+ ByteUtil.setThreeBytes(trailersFrameHeader, 0,
trailersPayload.limit());
+ trailersFrameHeader[3] = FrameType.HEADERS.getIdByte();
+ // Flags. end of headers (0x04) and end of stream (0x01)
+ trailersFrameHeader[4] = 0x05;
+ // Stream id
+ ByteUtil.set31Bits(trailersFrameHeader, 5, streamId);
+ }
}
@@ -1049,6 +1077,12 @@ public abstract class Http2TestBase exte
ByteArrayInputStream bais = new
ByteArrayInputStream(baos.toByteArray());
IOTools.flow(bais, resp.getOutputStream());
+
+ // Check for trailer headers
+ String trailerValue = req.getHeader(TRAILER_HEADER_NAME);
+ if (trailerValue != null) {
+
resp.getOutputStream().write(trailerValue.getBytes(StandardCharsets.UTF_8));
+ }
}
}
Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java
(original)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java Wed Oct
19 13:31:26 2016
@@ -33,6 +33,44 @@ import org.junit.Test;
public class TestHttp2Section_8_1 extends Http2TestBase {
@Test
+ public void testPostWithTrailerHeaders() throws Exception {
+ http2Connect();
+
+ byte[] headersFrameHeader = new byte[9];
+ ByteBuffer headersPayload = ByteBuffer.allocate(128);
+ byte[] dataFrameHeader = new byte[9];
+ ByteBuffer dataPayload = ByteBuffer.allocate(256);
+ byte[] trailerFrameHeader = new byte[9];
+ ByteBuffer trailerPayload = ByteBuffer.allocate(256);
+
+ buildPostRequest(headersFrameHeader, headersPayload, false,
dataFrameHeader, dataPayload,
+ null, trailerFrameHeader, trailerPayload, 3);
+
+ // Write the headers
+ writeFrame(headersFrameHeader, headersPayload);
+ // Body
+ writeFrame(dataFrameHeader, dataPayload);
+ // Trailers
+ writeFrame(trailerFrameHeader, trailerPayload);
+
+ parser.readFrame(true);
+ parser.readFrame(true);
+ parser.readFrame(true);
+ parser.readFrame(true);
+
+ Assert.assertEquals("0-WindowSize-[256]\n" +
+ "3-WindowSize-[256]\n" +
+ "3-HeadersStart\n" +
+ "3-Header-[:status]-[200]\n" +
+ "3-Header-[date]-["+ DEFAULT_DATE + "]\n" +
+ "3-HeadersEnd\n" +
+ "3-Body-260\n" +
+ "3-EndOfStream\n",
+ output.getTrace());
+ }
+
+
+ @Test
public void testSendAck() throws Exception {
http2Connect();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]