You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2016/09/27 17:50:56 UTC
svn commit: r1762528 - in /httpcomponents/httpcore/trunk/httpcore5-h2/src:
main/java/org/apache/hc/core5/http2/impl/nio/
main/java/org/apache/hc/core5/http2/nio/
main/java/org/apache/hc/core5/http2/nio/entity/
test/java/org/apache/hc/core5/http2/integr...
Author: olegk
Date: Tue Sep 27 17:50:56 2016
New Revision: 1762528
URL: http://svn.apache.org/viewvc?rev=1762528&view=rev
Log:
RFC 7230: Expect-continue handshake for HTTP/2 streams
Added:
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ExpectationChannel.java
- copied, changed from r1762527, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java
Modified:
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/MessageState.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityProducer.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/SharedOutputBuffer.java
httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2IntegrationTest.java
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamHandler.java Tue Sep 27 17:50:56 2016
@@ -35,26 +35,27 @@ import org.apache.hc.core5.concurrent.Fu
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http2.H2ConnectionException;
-import org.apache.hc.core5.http2.H2Error;
import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
-import org.apache.hc.core5.http2.nio.AsyncPushProducer;
import org.apache.hc.core5.http2.nio.AsyncRequestProducer;
import org.apache.hc.core5.http2.nio.AsyncResponseConsumer;
+import org.apache.hc.core5.http2.nio.DataStreamChannel;
class ClientHttp2StreamHandler<T> implements Http2StreamHandler {
- private final Http2StreamChannel internalOutputChannel;
+ private final Http2StreamChannel outputChannel;
+ private final DataStreamChannel dataChannel;
private final HttpProcessor httpProcessor;
private final BasicHttpConnectionMetrics connMetrics;
private final AsyncRequestProducer requestProducer;
@@ -74,23 +75,8 @@ class ClientHttp2StreamHandler<T> implem
final AsyncResponseConsumer<T> responseConsumer,
final HttpContext context,
final FutureCallback<T> resultCallback) {
- this.internalOutputChannel = new Http2StreamChannel() {
-
- @Override
- public void submit(final List<Header> headers, final boolean endStream) throws HttpException, IOException {
- outputChannel.submit(headers, endStream);
- requestState = endStream ? MessageState.COMPLETE : MessageState.BODY;
- }
-
- @Override
- public void push(final List<Header> headers, final AsyncPushProducer pushProducer) throws IOException {
- throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Push not allowed");
- }
-
- @Override
- public void update(final int increment) throws IOException {
- outputChannel.update(increment);
- }
+ this.outputChannel = outputChannel;
+ this.dataChannel = new DataStreamChannel() {
@Override
public void requestOutput() {
@@ -149,16 +135,26 @@ class ClientHttp2StreamHandler<T> implem
context.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
context.setAttribute(HttpCoreContext.HTTP_CONNECTION, this);
httpProcessor.process(request, entityDetails, context);
+ connMetrics.incrementRequestCount();
final List<Header> headers = DefaultH2RequestConverter.INSTANCE.convert(request);
- internalOutputChannel.submit(headers, entityDetails == null);
- connMetrics.incrementRequestCount();
- if (entityDetails != null) {
- requestProducer.dataStart(internalOutputChannel);
+ outputChannel.submit(headers, entityDetails == null);
+
+ if (entityDetails == null) {
+ requestState = MessageState.COMPLETE;
+ } else {
+ final Header h = request.getFirstHeader(HttpHeaders.EXPECT);
+ final boolean expectContinue = h != null && "100-continue".equalsIgnoreCase(h.getValue());
+ if (expectContinue) {
+ requestState = MessageState.ACK;
+ } else {
+ requestState = MessageState.BODY;
+ requestProducer.dataStart(dataChannel);
+ }
}
break;
case BODY:
- requestProducer.produce(internalOutputChannel);
+ requestProducer.produce(dataChannel);
break;
}
}
@@ -176,6 +172,14 @@ class ClientHttp2StreamHandler<T> implem
final HttpResponse response = DefaultH2ResponseConverter.INSTANCE.convert(headers);
final EntityDetails entityDetails = endStream ? null : new IncomingEntityDetails(response);
+ if (response.getCode() < 200) {
+ if (response.getCode() == HttpStatus.SC_CONTINUE && requestState == MessageState.ACK) {
+ requestState = MessageState.BODY;
+ requestProducer.dataStart(dataChannel);
+ }
+ return;
+ }
+
context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
httpProcessor.process(response, entityDetails, context);
connMetrics.incrementResponseCount();
@@ -214,7 +218,7 @@ class ClientHttp2StreamHandler<T> implem
@Override
public void updateInputCapacity() throws IOException {
- responseConsumer.updateCapacity(internalOutputChannel);
+ responseConsumer.updateCapacity(outputChannel);
}
@Override
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/MessageState.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/MessageState.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/MessageState.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/MessageState.java Tue Sep 27 17:50:56 2016
@@ -26,4 +26,4 @@
*/
package org.apache.hc.core5.http2.impl.nio;
-enum MessageState { IDLE, HEADERS, BODY, COMPLETE }
\ No newline at end of file
+enum MessageState { IDLE, HEADERS, ACK, BODY, COMPLETE }
\ No newline at end of file
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamHandler.java Tue Sep 27 17:50:56 2016
@@ -34,11 +34,14 @@ import java.util.concurrent.atomic.Atomi
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
+import org.apache.hc.core5.http.message.BasicHttpResponse;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
import org.apache.hc.core5.http2.H2ConnectionException;
@@ -48,19 +51,25 @@ import org.apache.hc.core5.http2.impl.De
import org.apache.hc.core5.http2.impl.IncomingEntityDetails;
import org.apache.hc.core5.http2.nio.AsyncExchangeHandler;
import org.apache.hc.core5.http2.nio.AsyncPushProducer;
+import org.apache.hc.core5.http2.nio.DataStreamChannel;
+import org.apache.hc.core5.http2.nio.ExpectationChannel;
import org.apache.hc.core5.http2.nio.HandlerFactory;
import org.apache.hc.core5.http2.nio.ResponseChannel;
import org.apache.hc.core5.util.Asserts;
public class ServerHttp2StreamHandler implements Http2StreamHandler {
- private final Http2StreamChannel internalOutputChannel;
+ private final Http2StreamChannel outputChannel;
+ private final DataStreamChannel dataChannel;
private final HttpProcessor httpProcessor;
private final BasicHttpConnectionMetrics connMetrics;
private final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory;
private final HttpCoreContext context;
+ private final AtomicBoolean responseCommitted;
private final AtomicBoolean done;
+ private volatile HttpRequest request;
+ private volatile EntityDetails requestEntityDetails;
private volatile AsyncExchangeHandler exchangeHandler;
private volatile MessageState requestState;
private volatile MessageState responseState;
@@ -70,23 +79,8 @@ public class ServerHttp2StreamHandler im
final HttpProcessor httpProcessor,
final BasicHttpConnectionMetrics connMetrics,
final HandlerFactory<AsyncExchangeHandler> exchangeHandlerFactory) {
- this.internalOutputChannel = new Http2StreamChannel() {
-
- @Override
- public void submit(final List<Header> headers, final boolean endStream) throws HttpException, IOException {
- outputChannel.submit(headers, endStream);
- responseState = endStream ? MessageState.COMPLETE : MessageState.BODY;
- }
-
- @Override
- public void push(final List<Header> headers, final AsyncPushProducer responseProducer) throws HttpException, IOException {
- outputChannel.push(headers, responseProducer);
- }
-
- @Override
- public void update(final int increment) throws IOException {
- outputChannel.update(increment);
- }
+ this.outputChannel = outputChannel;
+ this.dataChannel = new DataStreamChannel() {
@Override
public void requestOutput() {
@@ -115,11 +109,53 @@ public class ServerHttp2StreamHandler im
this.connMetrics = connMetrics;
this.exchangeHandlerFactory = exchangeHandlerFactory;
this.context = HttpCoreContext.create();
+ this.responseCommitted = new AtomicBoolean(false);
this.done = new AtomicBoolean(false);
this.requestState = MessageState.HEADERS;
this.responseState = MessageState.IDLE;
}
+ private void commitResponse(
+ final HttpResponse response,
+ final EntityDetails responseEntityDetails) throws HttpException, IOException {
+ if (responseCommitted.compareAndSet(false, true)) {
+
+ context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
+ httpProcessor.process(response, responseEntityDetails, context);
+
+ final List<Header> responseHeaders = DefaultH2ResponseConverter.INSTANCE.convert(response);
+
+ outputChannel.submit(responseHeaders, responseEntityDetails == null);
+ connMetrics.incrementResponseCount();
+ if (responseEntityDetails == null) {
+ responseState = MessageState.COMPLETE;
+ } else {
+ responseState = MessageState.BODY;
+ exchangeHandler.produce(dataChannel);
+ }
+ } else {
+ throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Response already committed");
+ }
+ }
+
+ private void commitPromise(
+ final HttpRequest promise,
+ final AsyncPushProducer pushProducer) throws HttpException, IOException {
+
+ httpProcessor.process(promise, null, context);
+
+ final List<Header> promiseHeaders = DefaultH2RequestConverter.INSTANCE.convert(promise);
+ outputChannel.push(promiseHeaders, pushProducer);
+ connMetrics.incrementRequestCount();
+ }
+
+ private void commitContinue() throws IOException, HttpException {
+ final HttpResponse ack = new BasicHttpResponse(HttpStatus.SC_CONTINUE);
+ final List<Header> responseHeaders = DefaultH2ResponseConverter.INSTANCE.convert(ack);
+
+ outputChannel.submit(responseHeaders, false);
+ }
+
@Override
public void consumePromise(final List<Header> headers) throws HttpException, IOException {
throw new ProtocolException("Unexpected message promise");
@@ -146,52 +182,68 @@ public class ServerHttp2StreamHandler im
throw new H2ConnectionException(H2Error.INTERNAL_ERROR,
"Unable to handle " + request.getMethod() + " " + request.getPath());
}
- exchangeHandler.handleRequest(request, requestEntityDetails, new ResponseChannel() {
- private final AtomicBoolean responseCommitted = new AtomicBoolean(false);
+ boolean expectContinue = false;
+ if (requestEntityDetails != null) {
+ final Header h = request.getFirstHeader(HttpHeaders.EXPECT);
+ if ("100-continue".equalsIgnoreCase(h.getValue())) {
+ expectContinue = true;
+ }
+ }
- @Override
- public void sendResponse(
- final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
- if (responseCommitted.compareAndSet(false, true)) {
-
- context.setAttribute(HttpCoreContext.HTTP_RESPONSE, response);
- httpProcessor.process(response, responseEntityDetails, context);
-
- final List<Header> responseHeaders = DefaultH2ResponseConverter.INSTANCE.convert(response);
-
- internalOutputChannel.submit(responseHeaders, responseEntityDetails == null);
- connMetrics.incrementResponseCount();
- if (responseEntityDetails != null) {
- exchangeHandler.produce(internalOutputChannel);
- }
- } else {
- throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Response already committed");
+ if (expectContinue) {
+ exchangeHandler.verify(request, requestEntityDetails, new ExpectationChannel() {
+
+ @Override
+ public void sendResponse(
+ final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
+ commitResponse(response, responseEntityDetails);
}
- }
- @Override
- public void pushPromise(final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
+ @Override
+ public void sendContinue() throws HttpException, IOException {
+ commitContinue();
+ exchangeHandler.handleRequest(request, requestEntityDetails, new ResponseChannel() {
+
+ @Override
+ public void sendResponse(
+ final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
+ commitResponse(response, responseEntityDetails);
+ }
+
+ @Override
+ public void pushPromise(
+ final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
+ commitPromise(promise, pushProducer);
+ }
- httpProcessor.process(promise, null, context);
+ });
+ }
- final List<Header> promiseHeaders = DefaultH2RequestConverter.INSTANCE.convert(promise);
- internalOutputChannel.push(promiseHeaders, pushProducer);
- connMetrics.incrementRequestCount();
- }
+ });
+ } else {
+ exchangeHandler.handleRequest(request, requestEntityDetails, new ResponseChannel() {
+
+ @Override
+ public void sendResponse(
+ final HttpResponse response, final EntityDetails responseEntityDetails) throws HttpException, IOException {
+ commitResponse(response, responseEntityDetails);
+ }
- @Override
- public String toString() {
- return internalOutputChannel.toString();
- }
+ @Override
+ public void pushPromise(
+ final HttpRequest promise, final AsyncPushProducer pushProducer) throws HttpException, IOException {
+ commitPromise(promise, pushProducer);
+ }
- });
+ });
+ }
}
@Override
public void updateInputCapacity() throws IOException {
Asserts.notNull(exchangeHandler, "Exchange handler");
- exchangeHandler.updateCapacity(internalOutputChannel);
+ exchangeHandler.updateCapacity(outputChannel);
}
@Override
@@ -218,7 +270,7 @@ public class ServerHttp2StreamHandler im
public void produceOutput() throws HttpException, IOException {
if (responseState == MessageState.BODY) {
Asserts.notNull(exchangeHandler, "Exchange handler");
- exchangeHandler.produce(internalOutputChannel);
+ exchangeHandler.produce(dataChannel);
}
}
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerPushHttp2StreamHandler.java Tue Sep 27 17:50:56 2016
@@ -41,16 +41,16 @@ import org.apache.hc.core5.http.Protocol
import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http2.H2ConnectionException;
-import org.apache.hc.core5.http2.H2Error;
import org.apache.hc.core5.http2.impl.DefaultH2RequestConverter;
import org.apache.hc.core5.http2.impl.DefaultH2ResponseConverter;
import org.apache.hc.core5.http2.nio.AsyncPushProducer;
+import org.apache.hc.core5.http2.nio.DataStreamChannel;
import org.apache.hc.core5.http2.nio.ResponseChannel;
class ServerPushHttp2StreamHandler implements Http2StreamHandler {
- private final Http2StreamChannel internalOutputChannel;
+ private final Http2StreamChannel outputChannel;
+ private final DataStreamChannel dataChannel;
private final HttpProcessor httpProcessor;
private final BasicHttpConnectionMetrics connMetrics;
private final AsyncPushProducer pushProducer;
@@ -65,23 +65,8 @@ class ServerPushHttp2StreamHandler imple
final HttpProcessor httpProcessor,
final BasicHttpConnectionMetrics connMetrics,
final AsyncPushProducer pushProducer) {
- this.internalOutputChannel = new Http2StreamChannel() {
-
- @Override
- public void submit(final List<Header> headers, final boolean endStream) throws HttpException, IOException {
- outputChannel.submit(headers, endStream);
- responseState = endStream ? MessageState.COMPLETE : MessageState.BODY;
- }
-
- @Override
- public void push(final List<Header> headers, final AsyncPushProducer pushProducer) throws IOException {
- throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Push not allowed");
- }
-
- @Override
- public void update(final int increment) throws IOException {
- outputChannel.update(increment);
- }
+ this.outputChannel = outputChannel;
+ this.dataChannel = new DataStreamChannel() {
@Override
public void requestOutput() {
@@ -166,7 +151,8 @@ class ServerPushHttp2StreamHandler imple
httpProcessor.process(response, entityDetails, context);
final List<Header> headers = DefaultH2ResponseConverter.INSTANCE.convert(response);
- internalOutputChannel.submit(headers, entityDetails == null);
+ outputChannel.submit(headers, entityDetails == null);
+ responseState = entityDetails == null ? MessageState.COMPLETE : MessageState.BODY;
connMetrics.incrementResponseCount();
}
}
@@ -182,14 +168,14 @@ class ServerPushHttp2StreamHandler imple
final List<Header> headers = DefaultH2RequestConverter.INSTANCE.convert(promise);
- internalOutputChannel.push(headers, pushProducer);
+ outputChannel.push(headers, pushProducer);
connMetrics.incrementRequestCount();
}
});
break;
case BODY:
- pushProducer.produce(internalOutputChannel);
+ pushProducer.produce(dataChannel);
break;
}
}
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractAsyncExchangeHandler.java Tue Sep 27 17:50:56 2016
@@ -72,6 +72,14 @@ public abstract class AbstractAsyncExcha
protected abstract void handle(Message<HttpRequest, T> request, AsyncResponseTrigger responseTrigger) throws IOException, HttpException;
@Override
+ public void verify(
+ final HttpRequest request,
+ final EntityDetails entityDetails,
+ final ExpectationChannel expectationChannel) throws HttpException, IOException {
+ expectationChannel.sendContinue();
+ }
+
+ @Override
public final void handleRequest(
final HttpRequest request,
final EntityDetails entityDetails,
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AbstractClassicExchangeHandler.java Tue Sep 27 17:50:56 2016
@@ -85,6 +85,14 @@ public abstract class AbstractClassicExc
HttpResponse response, OutputStream responseStream) throws IOException, HttpException;
@Override
+ public void verify(
+ final HttpRequest request,
+ final EntityDetails entityDetails,
+ final ExpectationChannel expectationChannel) throws HttpException, IOException {
+ expectationChannel.sendContinue();
+ }
+
+ @Override
public final void handleRequest(
final HttpRequest request,
final EntityDetails entityDetails,
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java Tue Sep 27 17:50:56 2016
@@ -39,6 +39,8 @@ import org.apache.hc.core5.http.HttpRequ
*/
public interface AsyncExchangeHandler extends AsyncDataConsumer, AsyncDataProducer {
+ void verify(HttpRequest request, EntityDetails entityDetails, ExpectationChannel expectationChannel) throws HttpException, IOException;
+
void handleRequest(HttpRequest request, EntityDetails entityDetails, ResponseChannel responseChannel) throws HttpException, IOException;
void failed(Exception cause);
Copied: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ExpectationChannel.java (from r1762527, httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java)
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ExpectationChannel.java?p2=httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ExpectationChannel.java&p1=httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java&r1=1762527&r2=1762528&rev=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/AsyncExchangeHandler.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/ExpectationChannel.java Tue Sep 27 17:50:56 2016
@@ -24,23 +24,29 @@
* <http://www.apache.org/>.
*
*/
+
package org.apache.hc.core5.http2.nio;
import java.io.IOException;
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.HttpException;
-import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
/**
- * Abstract asynchronous message exchange handler that acts as a request consumer and a response producer.
+ * Abstract expect-continue handshake channel.
+ * <p>
+ * Implementations are expected to be thread-safe.
*
* @since 5.0
*/
-public interface AsyncExchangeHandler extends AsyncDataConsumer, AsyncDataProducer {
+@Contract(threading = ThreadingBehavior.SAFE)
+public interface ExpectationChannel {
- void handleRequest(HttpRequest request, EntityDetails entityDetails, ResponseChannel responseChannel) throws HttpException, IOException;
+ void sendResponse(HttpResponse response, EntityDetails entityDetails) throws HttpException, IOException;
- void failed(Exception cause);
+ void sendContinue() throws HttpException, IOException;
}
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityProducer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityProducer.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityProducer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/AbstractClassicEntityProducer.java Tue Sep 27 17:50:56 2016
@@ -78,6 +78,7 @@ public abstract class AbstractClassicEnt
});
}
+ buffer.flush(channel);
}
@Override
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/SharedOutputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/SharedOutputBuffer.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/SharedOutputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/entity/SharedOutputBuffer.java Tue Sep 27 17:50:56 2016
@@ -47,7 +47,7 @@ public final class SharedOutputBuffer ex
public SharedOutputBuffer(final ReentrantLock lock, final int buffersize) {
super(lock, buffersize);
- this.hasCapacity = true;
+ this.hasCapacity = false;
}
public SharedOutputBuffer(final int buffersize) {
Modified: httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2IntegrationTest.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2IntegrationTest.java?rev=1762528&r1=1762527&r2=1762528&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2IntegrationTest.java (original)
+++ httpcomponents/httpcore/trunk/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/integration/Http2IntegrationTest.java Tue Sep 27 17:50:56 2016
@@ -78,6 +78,7 @@ import org.apache.hc.core5.http2.nio.Bas
import org.apache.hc.core5.http2.nio.BasicResponseProducer;
import org.apache.hc.core5.http2.nio.CapacityChannel;
import org.apache.hc.core5.http2.nio.DataStreamChannel;
+import org.apache.hc.core5.http2.nio.ExpectationChannel;
import org.apache.hc.core5.http2.nio.ResponseChannel;
import org.apache.hc.core5.http2.nio.StreamChannel;
import org.apache.hc.core5.http2.nio.Supplier;
@@ -350,6 +351,14 @@ public class Http2IntegrationTest extend
}
@Override
+ public void verify(
+ final HttpRequest request,
+ final EntityDetails entityDetails,
+ final ExpectationChannel expectationChannel) throws HttpException, IOException {
+ expectationChannel.sendContinue();
+ }
+
+ @Override
public void handleRequest(
final HttpRequest request,
final EntityDetails entityDetails,