279725 Support 100 and 102 expectations

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@356 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-06-10 02:17:34 +00:00
parent 4a38907a2c
commit 963fd5da81
8 changed files with 83 additions and 40 deletions

View File

@ -8,6 +8,7 @@ jetty-7.0.0.M3-SNAPSHOT
+ Portable continuations for jetty6 and servlet3 + Portable continuations for jetty6 and servlet3
+ Refactored continuations to only support response wrapping + Refactored continuations to only support response wrapping
+ Added ContinuationThrowable + Added ContinuationThrowable
+ 279725 Support 100 and 102 expectations
jetty-7.0.0.M2 18 May 2009 jetty-7.0.0.M2 18 May 2009
+ JETTY-937 Work around Sun JVM bugs + JETTY-937 Work around Sun JVM bugs

View File

@ -216,7 +216,7 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
if (attachment instanceof HttpDestination) if (attachment instanceof HttpDestination)
((HttpDestination)attachment).onConnectionFailed(ex); ((HttpDestination)attachment).onConnectionFailed(ex);
else else
Log.warn(ex); super.connectionFailed(channel,ex,attachment);
} }
} }
} }

View File

@ -3,7 +3,6 @@ package org.eclipse.jetty.continuation;
import java.util.EventListener; import java.util.EventListener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestListener; import javax.servlet.ServletRequestListener;

View File

@ -245,7 +245,8 @@ public abstract class SelectorManager extends AbstractLifeCycle
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
protected void connectionFailed(SocketChannel channel,Throwable ex,Object attachment) protected void connectionFailed(SocketChannel channel,Throwable ex,Object attachment)
{ {
Log.warn(ex); Log.warn(ex+","+channel+","+attachment);
Log.debug(ex);
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */

View File

@ -98,11 +98,14 @@ public class HttpConnection implements Connection
private Object _associatedObject; // associated object private Object _associatedObject; // associated object
private transient int _expect = UNKNOWN; private int _version = UNKNOWN;
private transient int _version = UNKNOWN;
private transient boolean _head = false; private boolean _expect = false;
private transient boolean _host = false; private boolean _expect100Continue = false;
private transient boolean _delayedHandling=false; private boolean _expect102Processing = false;
private boolean _head = false;
private boolean _host = false;
private boolean _delayedHandling=false;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public static HttpConnection getCurrentConnection() public static HttpConnection getCurrentConnection()
@ -288,12 +291,19 @@ public class HttpConnection implements Connection
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return The input stream for this connection. The stream will be created if it does not already exist. * Get the inputStream from the connection.
* <p>
* 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.
*
* @return The input stream for this connection.
* The stream will be created if it does not already exist.
*/ */
public ServletInputStream getInputStream() throws IOException public ServletInputStream getInputStream() throws IOException
{ {
// If the client is expecting 100 CONTINUE, then send it now. // If the client is expecting 100 CONTINUE, then send it now.
if (_expect == HttpHeaderValues.CONTINUE_ORDINAL) if (_expect100Continue)
{ {
if (((HttpParser)_parser).getHeaderBuffer()==null || ((HttpParser)_parser).getHeaderBuffer().length()<2) if (((HttpParser)_parser).getHeaderBuffer()==null || ((HttpParser)_parser).getHeaderBuffer().length()<2)
{ {
@ -302,7 +312,7 @@ public class HttpConnection implements Connection
_generator.complete(); _generator.complete();
_generator.reset(false); _generator.reset(false);
} }
_expect = UNKNOWN; _expect100Continue=false;
} }
if (_in == null) if (_in == null)
@ -593,10 +603,10 @@ public class HttpConnection implements Connection
{ {
_request._async.doComplete(); _request._async.doComplete();
if (_expect == HttpHeaderValues.CONTINUE_ORDINAL) if (_expect100Continue)
{ {
// Continue not sent so don't parse any content // Continue not sent so don't parse any content
_expect = UNKNOWN; _expect100Continue = false;
if (_parser instanceof HttpParser) if (_parser instanceof HttpParser)
((HttpParser)_parser).setState(HttpParser.STATE_END); ((HttpParser)_parser).setState(HttpParser.STATE_END);
} }
@ -705,7 +715,17 @@ public class HttpConnection implements Connection
return _request.getAsyncContinuation().isSuspended(); return _request.getAsyncContinuation().isSuspended();
} }
/* ------------------------------------------------------------ */
public boolean isExpecting100Continues()
{
return _expect100Continue;
}
/* ------------------------------------------------------------ */
public boolean isExpecting102Processing()
{
return _expect102Processing;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -722,7 +742,9 @@ public class HttpConnection implements Connection
public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
{ {
_host = false; _host = false;
_expect = UNKNOWN; _expect = false;
_expect100Continue=false;
_expect102Processing=false;
_delayedHandling=false; _delayedHandling=false;
_charset=null; _charset=null;
@ -771,7 +793,39 @@ public class HttpConnection implements Connection
case HttpHeaders.EXPECT_ORDINAL: case HttpHeaders.EXPECT_ORDINAL:
value = HttpHeaderValues.CACHE.lookup(value); value = HttpHeaderValues.CACHE.lookup(value);
_expect = HttpHeaderValues.CACHE.getOrdinal(value); switch(HttpHeaderValues.CACHE.getOrdinal(value))
{
case HttpHeaderValues.CONTINUE_ORDINAL:
_expect100Continue=true;
break;
case HttpHeaderValues.PROCESSING_ORDINAL:
_expect102Processing=true;
break;
default:
String[] values = value.toString().split(",");
for (int i=0;values!=null && i<values.length;i++)
{
CachedBuffer cb=HttpHeaderValues.CACHE.get(values[i].trim());
if (cb==null)
_expect=true;
else
{
switch(cb.getOrdinal())
{
case HttpHeaderValues.CONTINUE_ORDINAL:
_expect100Continue=true;
break;
case HttpHeaderValues.PROCESSING_ORDINAL:
_expect102Processing=true;
break;
default:
_expect=true;
}
}
}
}
break; break;
case HttpHeaders.ACCEPT_ENCODING_ORDINAL: case HttpHeaders.ACCEPT_ENCODING_ORDINAL:
@ -786,8 +840,7 @@ public class HttpConnection implements Connection
case HttpHeaders.CONNECTION_ORDINAL: case HttpHeaders.CONNECTION_ORDINAL:
//looks rather clumsy, but the idea is to optimize for a single valued header //looks rather clumsy, but the idea is to optimize for a single valued header
int ordinal = HttpHeaderValues.CACHE.getOrdinal(value); switch(HttpHeaderValues.CACHE.getOrdinal(value))
switch(ordinal)
{ {
case -1: case -1:
{ {
@ -858,20 +911,11 @@ public class HttpConnection implements Connection
return; return;
} }
if (_expect != UNKNOWN) if (_expect)
{
if (_expect == HttpHeaderValues.CONTINUE_ORDINAL)
{
}
else if (_expect == HttpHeaderValues.PROCESSING_ORDINAL)
{
}
else
{ {
_generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true); _generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true);
return; return;
} }
}
break; break;
default: default:
@ -881,7 +925,7 @@ public class HttpConnection implements Connection
_request.setCharacterEncodingUnchecked(_charset); _request.setCharacterEncodingUnchecked(_charset);
// Either handle now or wait for first content // Either handle now or wait for first content
if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect==HttpHeaderValues.CONTINUE_ORDINAL) if ((((HttpParser)_parser).getContentLength()<=0 && !((HttpParser)_parser).isChunking())||_expect100Continue)
handleRequest(); handleRequest();
else else
_delayedHandling=true; _delayedHandling=true;
@ -900,6 +944,7 @@ public class HttpConnection implements Connection
} }
} }
/* ------------------------------------------------------------ */
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -914,6 +959,7 @@ public class HttpConnection implements Connection
} }
} }
/* ------------------------------------------------------------ */
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -924,7 +970,6 @@ public class HttpConnection implements Connection
{ {
Log.debug("Bad request!: "+version+" "+status+" "+reason); Log.debug("Bad request!: "+version+" "+status+" "+reason);
} }
} }

View File

@ -382,16 +382,13 @@ public class Response implements HttpServletResponse
* @see javax.servlet.http.HttpServletResponse#sendError(int) * @see javax.servlet.http.HttpServletResponse#sendError(int)
*/ */
public void sendProcessing() throws IOException public void sendProcessing() throws IOException
{
if (_connection.isExpecting102Processing())
{ {
Generator g = _connection.getGenerator(); Generator g = _connection.getGenerator();
if (g instanceof HttpGenerator) if (g instanceof HttpGenerator)
{ {
HttpGenerator generator = (HttpGenerator)g; HttpGenerator generator = (HttpGenerator)g;
String expect = _connection.getRequest().getHeader(HttpHeaders.EXPECT);
if (expect!=null && expect.startsWith("102") && generator.getVersion()>=HttpVersions.HTTP_1_1_ORDINAL)
{
boolean was_persistent=generator.isPersistent(); boolean was_persistent=generator.isPersistent();
generator.setResponse(102,null); generator.setResponse(102,null);
generator.completeHeader(null,true); generator.completeHeader(null,true);