Author: markt
Date: Wed Sep 30 23:33:55 2015
New Revision: 1706173
URL: http://svn.apache.org/viewvc?rev=1706173&view=rev
Log:
Add 100-continue support to HTTP/2
Added:
tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java (with
props)
Modified:
tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
tomcat/trunk/java/org/apache/coyote/http2/Stream.java
tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java
tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.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=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed Sep
30 23:33:55 2015
@@ -458,7 +458,8 @@ public class Http2UpgradeHandler extends
}
- void writeHeaders(Stream stream, Response coyoteResponse) throws
IOException {
+ void writeHeaders(Stream stream, Response coyoteResponse, int payloadSize)
+ throws IOException {
if (log.isDebugEnabled()) {
log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId,
stream.getIdentifier()));
@@ -468,10 +469,8 @@ public class Http2UpgradeHandler extends
headers.addValue(":status").setString(Integer.toString(coyoteResponse.getStatus()));
// This ensures the Stream processing thread has control of the socket.
synchronized (socketWrapper) {
- // Frame sizes are allowed to be bigger than 4k but for headers
that
- // should be plenty
byte[] header = new byte[9];
- ByteBuffer target = ByteBuffer.allocate(4 * 1024);
+ ByteBuffer target = ByteBuffer.allocate(payloadSize);
boolean first = true;
State state = null;
while (state != State.COMPLETE) {
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=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed Sep 30 23:33:55
2015
@@ -37,6 +37,12 @@ public class Stream extends AbstractStre
private static final Log log = LogFactory.getLog(Stream.class);
private static final StringManager sm =
StringManager.getManager(Stream.class);
+ private static final Response ACK_RESPONSE = new Response();
+
+ static {
+ ACK_RESPONSE.setStatus(101);
+ }
+
private volatile int weight = Constants.DEFAULT_WEIGHT;
private final Http2UpgradeHandler handler;
@@ -225,6 +231,9 @@ public class Stream extends AbstractStre
break;
}
default: {
+ if ("expect".equals(name) && "100-continue".equals(value)) {
+ coyoteRequest.setExpectation(true);
+ }
// Assume other HTTP header
coyoteRequest.getMimeHeaders().addValue(name).setString(value);
}
@@ -233,9 +242,16 @@ public class Stream extends AbstractStre
void writeHeaders() throws IOException {
- handler.writeHeaders(this, coyoteResponse);
+ // TODO: Is 1k the optimal value?
+ handler.writeHeaders(this, coyoteResponse, 1024);
}
+ void writeAck() throws IOException {
+ // TODO: Is 64 too big? Just the status header with compression
+ handler.writeHeaders(this, ACK_RESPONSE, 64);
+ }
+
+
void flushData() throws IOException {
if (log.isDebugEnabled()) {
Modified: tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java?rev=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java Wed Sep 30
23:33:55 2015
@@ -139,6 +139,16 @@ public class StreamProcessor extends Abs
}
break;
}
+ case ACK: {
+ if (!response.isCommitted() && request.hasExpectation()) {
+ try {
+ stream.writeAck();
+ } catch (IOException ioe) {
+ // TODO
+ }
+ }
+ break;
+ }
case CLIENT_FLUSH: {
action(ActionCode.COMMIT, null);
try {
@@ -330,7 +340,6 @@ public class StreamProcessor extends Abs
sm.getString("streamProcessor.httpupgrade.notsupported"));
// Unimplemented / to review
- case ACK:
case CLOSE_NOW:
case DISABLE_SWALLOW_INPUT:
case END_REQUEST:
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=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Wed Sep 30
23:33:55 2015
@@ -232,12 +232,17 @@ public abstract class Http2TestBase exte
protected void sendSimplePostRequest(int streamId, byte[] padding, boolean
writeBody)
throws IOException {
+ sendSimplePostRequest(streamId, padding, writeBody, false);
+ }
+
+ protected void sendSimplePostRequest(int streamId, byte[] padding, boolean
writeBody,
+ boolean useExpectation) throws IOException {
byte[] headersFrameHeader = new byte[9];
ByteBuffer headersPayload = ByteBuffer.allocate(128);
byte[] dataFrameHeader = new byte[9];
ByteBuffer dataPayload = ByteBuffer.allocate(128);
- buildPostRequest(headersFrameHeader, headersPayload,
+ buildPostRequest(headersFrameHeader, headersPayload, useExpectation,
dataFrameHeader, dataPayload, padding, streamId);
writeFrame(headersFrameHeader, headersPayload);
if (writeBody) {
@@ -247,11 +252,15 @@ public abstract class Http2TestBase exte
protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer
headersPayload,
- byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
int streamId) {
+ boolean useExpectation, byte[] dataFrameHeader, ByteBuffer
dataPayload, byte[] padding,
+ int streamId) {
MimeHeaders headers = new MimeHeaders();
headers.addValue(":method").setString("POST");
headers.addValue(":path").setString("/simple");
headers.addValue(":authority").setString("localhost:" + getPort());
+ if (useExpectation) {
+ headers.addValue("expect").setString("100-continue");
+ }
hpackEncoder.encode(headers, headersPayload);
headersPayload.flip();
Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java?rev=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
(original)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java Wed Sep
30 23:33:55 2015
@@ -167,7 +167,7 @@ public class TestHttp2Section_6_9 extend
byte[] dataFrameHeader = new byte[9];
ByteBuffer dataPayload = ByteBuffer.allocate(8 * 1024);
- buildPostRequest(headersFrameHeader, headersPayload,
+ buildPostRequest(headersFrameHeader, headersPayload, false,
dataFrameHeader, dataPayload, null, 3);
// Write the headers
Added: 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=1706173&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java (added)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java Wed Sep
30 23:33:55 2015
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.coyote.http2;
+
+import java.nio.ByteBuffer;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit tests for Section 8.1 of
+ * <a href="https://tools.ietf.org/html/rfc7540">RFC 7540</a>.
+ * <br>
+ * The order of tests in this class is aligned with the order of the
+ * examples in the RFC.
+ */
+public class TestHttp2Section_8_1 extends Http2TestBase {
+
+ @Test
+ public void testPostWithContinuation() throws Exception {
+ http2Connect();
+
+ }
+
+ @Test
+ public void testSendAck() throws Exception {
+ http2Connect();
+
+ byte[] headersFrameHeader = new byte[9];
+ ByteBuffer headersPayload = ByteBuffer.allocate(128);
+ byte[] dataFrameHeader = new byte[9];
+ ByteBuffer dataPayload = ByteBuffer.allocate(256);
+
+ buildPostRequest(headersFrameHeader, headersPayload, true,
+ dataFrameHeader, dataPayload, null, 3);
+
+ // Write the headers
+ writeFrame(headersFrameHeader, headersPayload);
+
+ parser.readFrame(true);
+
+ Assert.assertEquals("3-HeadersStart\n" +
+ "3-Header-[:status]-[101]\n" +
+ "3-HeadersEnd\n",
+ output.getTrace());
+ output.clearTrace();
+
+ // Write the body
+ writeFrame(dataFrameHeader, dataPayload);
+
+ 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-HeadersEnd\n" +
+ "3-Body-256\n" +
+ "3-EndOfStream\n",
+ output.getTrace());
+
+ }
+}
Propchange: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]