partial 100 continues support in http2

This commit is contained in:
Greg Wilkins 2014-08-05 16:14:53 +10:00
parent d7f2c42e2d
commit 6b3c8d06a9
3 changed files with 47 additions and 11 deletions

View File

@ -100,7 +100,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
HttpChannelOverHTTP2 channel = new HttpChannelOverHTTP2(connector, httpConfiguration, endPoint, transport, input, stream);
stream.setAttribute(CHANNEL_ATTRIBUTE, channel);
channel.requestHeaders(frame);
channel.onHeadersFrame(frame);
return frame.isEndStream() ? null : this;
}

View File

@ -18,11 +18,14 @@
package org.eclipse.jetty.http2.server;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.frames.DataFrame;
@ -46,6 +49,7 @@ public class HttpChannelOverHTTP2 extends HttpChannel
private static final HttpField SERVER_VERSION=new HttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION);
private static final HttpField POWERED_BY=new HttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
private final Stream stream; // TODO recycle channel for new Stream?
private boolean _expect100Continue = false;
public HttpChannelOverHTTP2(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput input, Stream stream)
{
@ -53,7 +57,13 @@ public class HttpChannelOverHTTP2 extends HttpChannel
this.stream = stream;
}
public void requestHeaders(HeadersFrame frame)
@Override
public boolean isExpecting100Continue()
{
return _expect100Continue;
}
public void onHeadersFrame(HeadersFrame frame)
{
MetaData metaData = frame.getMetaData();
if (!metaData.isRequest())
@ -63,22 +73,20 @@ public class HttpChannelOverHTTP2 extends HttpChannel
}
MetaData.Request request = (MetaData.Request)metaData;
// The specification says user agents MUST support gzip encoding.
// Based on that, some browser does not send the header, but it's
// important that applications can find it (e.g. GzipFilter).
HttpFields fields = request.getFields();
if (!fields.contains(HttpHeader.ACCEPT_ENCODING, "gzip"))
fields.add(ACCEPT_ENCODING_GZIP);
_expect100Continue = fields.contains(HttpHeader.EXPECT,HttpHeaderValue.CONTINUE.asString());
// TODO make this a better field for h2 hpack generation
HttpFields response=getResponse().getHttpFields();
if (getHttpConfiguration().getSendServerVersion())
getResponse().getHttpFields().add(SERVER_VERSION);
response.add(SERVER_VERSION);
if (getHttpConfiguration().getSendXPoweredBy())
getResponse().getHttpFields().add(POWERED_BY);
response.add(POWERED_BY);
onRequest(request);
if (frame.isEndStream())
{
onRequestComplete();
@ -127,4 +135,33 @@ public class HttpChannelOverHTTP2 extends HttpChannel
onRequestComplete();
}
}
/**
* If the associated response has the Expect header set to 100 Continue,
* then accessing the input stream indicates that the handler/servlet
* is ready for the request body and thus a 100 Continue response is sent.
*
* @throws IOException if the InputStream cannot be created
*/
@Override
public void continue100(int available) throws IOException
{
// If the client is expecting 100 CONTINUE, then send it now.
// TODO: consider using an AtomicBoolean ?
if (isExpecting100Continue())
{
_expect100Continue = false;
// is content missing?
if (available == 0)
{
if (getResponse().isCommitted())
throw new IOException("Committed before 100 Continues");
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
if (!committed)
throw new IOException("Concurrent commit while trying to send 100-Continue");
}
}
}
}

View File

@ -199,7 +199,6 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
if (getResponse().isCommitted())
throw new IOException("Committed before 100 Continues");
// TODO: break this dependency with HttpGenerator
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
if (!committed)
throw new IOException("Concurrent commit while trying to send 100-Continue");