Merge branch 'master' into jetty-9.4.x-Feature

This commit is contained in:
Greg Wilkins 2016-02-25 10:11:08 +01:00
commit add9876f83
31 changed files with 493 additions and 120 deletions

View File

@ -53,6 +53,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.ssl.SslBytesTest.TLSRecord.Type; import org.eclipse.jetty.client.ssl.SslBytesTest.TLSRecord.Type;
import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.io.ChannelEndPoint; import org.eclipse.jetty.io.ChannelEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
@ -114,7 +115,7 @@ public class SslBytesServerTest extends SslBytesTest
return configure(new HttpConnection(getHttpConfiguration(), connector, endPoint,getHttpCompliance()) return configure(new HttpConnection(getHttpConfiguration(), connector, endPoint,getHttpCompliance())
{ {
@Override @Override
protected HttpParser newHttpParser(HttpParser.Compliance compliance) protected HttpParser newHttpParser(HttpCompliance compliance)
{ {
return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize(),compliance) return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize(),compliance)
{ {

View File

@ -19,6 +19,12 @@
package org.eclipse.jetty.http; package org.eclipse.jetty.http;
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/**
* <p>Exception thrown to indicate a Bad HTTP Message has either been received
* or attempted to be generated. Typically these are handled with either 400
* or 500 responses.</p>
*/
@SuppressWarnings("serial")
public class BadMessageException extends RuntimeException public class BadMessageException extends RuntimeException
{ {
final int _code; final int _code;

View File

@ -0,0 +1,32 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.http;
/**
* HTTP compliance modes:
* <dl>
* <dt>RFC7230</dt><dd>(default) Compliance with RFC7230</dd>
* <dt>RFC2616</dt><dd>Wrapped/Continued headers and HTTP/0.9 supported</dd>
* <dt>LEGACY</dt><dd>(aka STRICT) Adherence to Servlet Specification requirement for
* exact case of header names, bypassing the header caches, which are case insensitive,
* otherwise equivalent to RFC2616</dd>
* </dl>
*/
public enum HttpCompliance { LEGACY, RFC2616, RFC7230 }

View File

@ -228,7 +228,7 @@ public class HttpGenerator
generateRequestLine(info,header); generateRequestLine(info,header);
if (info.getVersion()==HttpVersion.HTTP_0_9) if (info.getVersion()==HttpVersion.HTTP_0_9)
throw new IllegalArgumentException("HTTP/0.9 not supported"); throw new BadMessageException(500,"HTTP/0.9 not supported");
generateHeaders(info,header,content,last); generateHeaders(info,header,content,last);
@ -256,7 +256,7 @@ public class HttpGenerator
catch(Exception e) catch(Exception e)
{ {
String message= (e instanceof BufferOverflowException)?"Request header too large":e.getMessage(); String message= (e instanceof BufferOverflowException)?"Request header too large":e.getMessage();
throw new IOException(message,e); throw new BadMessageException(500,message,e);
} }
finally finally
{ {
@ -345,7 +345,7 @@ public class HttpGenerator
return Result.NEED_INFO; return Result.NEED_INFO;
HttpVersion version=info.getVersion(); HttpVersion version=info.getVersion();
if (version==null) if (version==null)
throw new IllegalStateException("No version"); throw new BadMessageException(500,"No version");
switch(version) switch(version)
{ {
case HTTP_1_0: case HTTP_1_0:
@ -359,7 +359,12 @@ public class HttpGenerator
break; break;
default: default:
throw new IllegalArgumentException(version+" not supported"); _persistent = false;
_endOfContent=EndOfContent.EOF_CONTENT;
if (BufferUtil.hasContent(content))
_contentPrepared+=content.remaining();
_state = last?State.COMPLETING:State.COMMITTED;
return Result.FLUSH;
} }
// Do we need a response header // Do we need a response header
@ -406,7 +411,7 @@ public class HttpGenerator
catch(Exception e) catch(Exception e)
{ {
String message= (e instanceof BufferOverflowException)?"Response header too large":e.getMessage(); String message= (e instanceof BufferOverflowException)?"Response header too large":e.getMessage();
throw new IOException(message,e); throw new BadMessageException(500,message,e);
} }
finally finally
{ {
@ -757,7 +762,7 @@ public class HttpGenerator
long actual_length = _contentPrepared+BufferUtil.length(content); long actual_length = _contentPrepared+BufferUtil.length(content);
if (content_length>=0 && content_length!=actual_length) if (content_length>=0 && content_length!=actual_length)
throw new IllegalArgumentException("Content-Length header("+content_length+") != actual("+actual_length+")"); throw new BadMessageException(500,"Content-Length header("+content_length+") != actual("+actual_length+")");
// Do we need to tell the headers about it // Do we need to tell the headers about it
putContentLength(header,actual_length,content_type,request,response); putContentLength(header,actual_length,content_type,request,response);
@ -782,7 +787,7 @@ public class HttpGenerator
} }
case NO_CONTENT: case NO_CONTENT:
throw new IllegalStateException(); throw new BadMessageException(500);
case EOF_CONTENT: case EOF_CONTENT:
_persistent = request!=null; _persistent = request!=null;
@ -805,7 +810,7 @@ public class HttpGenerator
if (c.endsWith(HttpHeaderValue.CHUNKED.toString())) if (c.endsWith(HttpHeaderValue.CHUNKED.toString()))
putTo(transfer_encoding,header); putTo(transfer_encoding,header);
else else
throw new IllegalArgumentException("BAD TE"); throw new BadMessageException(500,"BAD TE");
} }
else else
header.put(TRANSFER_ENCODING_CHUNKED); header.put(TRANSFER_ENCODING_CHUNKED);

View File

@ -77,12 +77,11 @@ import static org.eclipse.jetty.http.HttpTokens.TAB;
* The parser can work in varying compliance modes: * The parser can work in varying compliance modes:
* <dl> * <dl>
* <dt>RFC7230</dt><dd>(default) Compliance with RFC7230</dd> * <dt>RFC7230</dt><dd>(default) Compliance with RFC7230</dd>
* <dt>RFC2616</dt><dd>Wrapped headers supported</dd> * <dt>RFC2616</dt><dd>Wrapped headers and HTTP/0.9 supported</dd>
* <dt>STRICT</dt><dd>(misnomer) Adherence to Servlet Specification requirement for * <dt>LEGACY</dt><dd>(aka STRICT) Adherence to Servlet Specification requirement for
* exact case of header names, bypassing the header caches, which are case insensitive, * exact case of header names, bypassing the header caches, which are case insensitive,
* otherwise equivalent to RFC2616</dd> * otherwise equivalent to RFC2616</dd>
* </p> * </dl>
* <p>
* @see <a href="http://tools.ietf.org/html/rfc7230">RFC 7230</a> * @see <a href="http://tools.ietf.org/html/rfc7230">RFC 7230</a>
*/ */
public class HttpParser public class HttpParser
@ -106,9 +105,6 @@ public class HttpParser
*/ */
public final static Trie<HttpField> CACHE = new ArrayTrie<>(2048); public final static Trie<HttpField> CACHE = new ArrayTrie<>(2048);
// Compliance
public enum Compliance { STRICT, RFC2616, RFC7230 };
// States // States
public enum State public enum State
{ {
@ -146,7 +142,7 @@ public class HttpParser
private final RequestHandler _requestHandler; private final RequestHandler _requestHandler;
private final ResponseHandler _responseHandler; private final ResponseHandler _responseHandler;
private final int _maxHeaderBytes; private final int _maxHeaderBytes;
private final Compliance _compliance; private final HttpCompliance _compliance;
private HttpField _field; private HttpField _field;
private HttpHeader _header; private HttpHeader _header;
private String _headerString; private String _headerString;
@ -226,10 +222,10 @@ public class HttpParser
CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null)); CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null));
} }
private static Compliance compliance() private static HttpCompliance compliance()
{ {
Boolean strict = Boolean.getBoolean(__STRICT); Boolean strict = Boolean.getBoolean(__STRICT);
return strict?Compliance.STRICT:Compliance.RFC7230; return strict?HttpCompliance.LEGACY:HttpCompliance.RFC7230;
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@ -260,18 +256,24 @@ public class HttpParser
@Deprecated @Deprecated
public HttpParser(RequestHandler handler,int maxHeaderBytes,boolean strict) public HttpParser(RequestHandler handler,int maxHeaderBytes,boolean strict)
{ {
this(handler,maxHeaderBytes,strict?Compliance.STRICT:compliance()); this(handler,maxHeaderBytes,strict?HttpCompliance.LEGACY:compliance());
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@Deprecated @Deprecated
public HttpParser(ResponseHandler handler,int maxHeaderBytes,boolean strict) public HttpParser(ResponseHandler handler,int maxHeaderBytes,boolean strict)
{ {
this(handler,maxHeaderBytes,strict?Compliance.STRICT:compliance()); this(handler,maxHeaderBytes,strict?HttpCompliance.LEGACY:compliance());
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
public HttpParser(RequestHandler handler,int maxHeaderBytes,Compliance compliance) public HttpParser(RequestHandler handler,HttpCompliance compliance)
{
this(handler,-1,compliance);
}
/* ------------------------------------------------------------------------------- */
public HttpParser(RequestHandler handler,int maxHeaderBytes,HttpCompliance compliance)
{ {
_handler=handler; _handler=handler;
_requestHandler=handler; _requestHandler=handler;
@ -281,7 +283,7 @@ public class HttpParser
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
public HttpParser(ResponseHandler handler,int maxHeaderBytes,Compliance compliance) public HttpParser(ResponseHandler handler,int maxHeaderBytes,HttpCompliance compliance)
{ {
_handler=handler; _handler=handler;
_requestHandler=null; _requestHandler=null;
@ -583,7 +585,7 @@ public class HttpParser
_length=_string.length(); _length=_string.length();
_methodString=takeString(); _methodString=takeString();
HttpMethod method=HttpMethod.CACHE.get(_methodString); HttpMethod method=HttpMethod.CACHE.get(_methodString);
if (method!=null && _compliance!=Compliance.STRICT) if (method!=null && _compliance!=HttpCompliance.LEGACY)
_methodString=method.asString(); _methodString=method.asString();
setState(State.SPACE1); setState(State.SPACE1);
} }
@ -685,7 +687,15 @@ public class HttpParser
else if (ch < HttpTokens.SPACE && ch>=0) else if (ch < HttpTokens.SPACE && ch>=0)
{ {
// HTTP/0.9 // HTTP/0.9
throw new BadMessageException("HTTP/0.9 not supported"); if (_compliance.ordinal()>=HttpCompliance.RFC7230.ordinal())
throw new BadMessageException("HTTP/0.9 not supported");
handle=_requestHandler.startRequest(_methodString,_uri.toString(), HttpVersion.HTTP_0_9);
setState(State.END);
BufferUtil.clear(buffer);
handle=_handler.headerComplete()||handle;
handle=_handler.messageComplete()||handle;
return handle;
} }
else else
{ {
@ -747,7 +757,15 @@ public class HttpParser
else else
{ {
// HTTP/0.9 // HTTP/0.9
throw new BadMessageException("HTTP/0.9 not supported"); if (_compliance.ordinal()>=HttpCompliance.RFC7230.ordinal())
throw new BadMessageException("HTTP/0.9 not supported");
handle=_requestHandler.startRequest(_methodString,_uri.toString(), HttpVersion.HTTP_0_9);
setState(State.END);
BufferUtil.clear(buffer);
handle=_handler.headerComplete()||handle;
handle=_handler.messageComplete()||handle;
return handle;
} }
} }
else if (ch<0) else if (ch<0)
@ -859,7 +877,7 @@ public class HttpParser
_host=true; _host=true;
if (!(_field instanceof HostPortHttpField)) if (!(_field instanceof HostPortHttpField))
{ {
_field=new HostPortHttpField(_header,_compliance==Compliance.STRICT?_headerString:_header.asString(),_valueString); _field=new HostPortHttpField(_header,_compliance==HttpCompliance.LEGACY?_headerString:_header.asString(),_valueString);
add_to_connection_trie=_connectionFields!=null; add_to_connection_trie=_connectionFields!=null;
} }
break; break;
@ -888,7 +906,7 @@ public class HttpParser
if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null) if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null)
{ {
if (_field==null) if (_field==null)
_field=new HttpField(_header,_compliance==Compliance.STRICT?_headerString:_header.asString(),_valueString); _field=new HttpField(_header,_compliance==HttpCompliance.LEGACY?_headerString:_header.asString(),_valueString);
_connectionFields.put(_field); _connectionFields.put(_field);
} }
} }
@ -933,7 +951,7 @@ public class HttpParser
case HttpTokens.SPACE: case HttpTokens.SPACE:
case HttpTokens.TAB: case HttpTokens.TAB:
{ {
if (_compliance.ordinal()>=Compliance.RFC7230.ordinal()) if (_compliance.ordinal()>=HttpCompliance.RFC7230.ordinal())
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Continuation"); throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Continuation");
// header value without name - continuation? // header value without name - continuation?
@ -1035,7 +1053,7 @@ public class HttpParser
final String n; final String n;
final String v; final String v;
if (_compliance==Compliance.STRICT) if (_compliance==HttpCompliance.LEGACY)
{ {
// Have to get the fields exactly from the buffer to match case // Have to get the fields exactly from the buffer to match case
String fn=field.getName(); String fn=field.getName();

View File

@ -32,6 +32,41 @@ import org.junit.Test;
public class HttpGeneratorServerTest public class HttpGeneratorServerTest
{ {
@Test
public void test_0_9() throws Exception
{
ByteBuffer header = BufferUtil.allocate(8096);
ByteBuffer content = BufferUtil.toBuffer("0123456789");
HttpGenerator gen = new HttpGenerator();
HttpGenerator.Result result = gen.generateResponse(null, null, null, content, true);
assertEquals(HttpGenerator.Result.NEED_INFO, result);
assertEquals(HttpGenerator.State.START, gen.getState());
MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_0_9, 200, null, new HttpFields(), 10);
info.getFields().add("Content-Type", "test/data");
info.getFields().add("Last-Modified", DateGenerator.__01Jan1970);
result = gen.generateResponse(info, null, null, content, true);
assertEquals(HttpGenerator.Result.FLUSH, result);
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
String response = BufferUtil.toString(header);
BufferUtil.clear(header);
response += BufferUtil.toString(content);
BufferUtil.clear(content);
result = gen.generateResponse(null, null, null, content, false);
assertEquals(HttpGenerator.Result.SHUTDOWN_OUT, result);
assertEquals(HttpGenerator.State.END, gen.getState());
assertEquals(10, gen.getContentPrepared());
assertThat(response, not(containsString("200 OK")));
assertThat(response, not(containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT")));
assertThat(response, not(containsString("Content-Length: 10")));
assertThat(response, containsString("0123456789"));
}
@Test @Test
public void testSimple() throws Exception public void testSimple() throws Exception

View File

@ -114,19 +114,49 @@ public class HttpParserTest
assertEquals(-1, _headers); assertEquals(-1, _headers);
} }
@Test
public void testLineParse1_RFC2616() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer("GET /999\015\012");
HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler,HttpCompliance.RFC2616);
parseAll(parser,buffer);
assertNull(_bad);
assertEquals("GET", _methodOrVersion);
assertEquals("/999", _uriOrStatus);
assertEquals("HTTP/0.9", _versionOrReason);
assertEquals(-1, _headers);
}
@Test @Test
public void testLineParse1() throws Exception public void testLineParse1() throws Exception
{ {
ByteBuffer buffer= BufferUtil.toBuffer("GET /999\015\012"); ByteBuffer buffer= BufferUtil.toBuffer("GET /999\015\012");
_versionOrReason= null;
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler); HttpParser parser= new HttpParser(handler);
parseAll(parser,buffer); parseAll(parser,buffer);
assertEquals("HTTP/0.9 not supported", _bad); assertEquals("HTTP/0.9 not supported", _bad);
} }
@Test
public void testLineParse2_RFC2616() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer("POST /222 \015\012");
HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler,HttpCompliance.RFC2616);
parseAll(parser,buffer);
assertNull(_bad);
assertEquals("POST", _methodOrVersion);
assertEquals("/222", _uriOrStatus);
assertEquals("HTTP/0.9", _versionOrReason);
assertEquals(-1, _headers);
}
@Test @Test
public void testLineParse2() throws Exception public void testLineParse2() throws Exception
{ {
@ -136,7 +166,7 @@ public class HttpParserTest
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler); HttpParser parser= new HttpParser(handler);
parseAll(parser,buffer); parseAll(parser,buffer);
assertEquals("HTTP/0.9 not supported", _bad); assertEquals("HTTP/0.9 not supported", _bad);
} }
@Test @Test
@ -230,7 +260,7 @@ public class HttpParserTest
"\015\012"); "\015\012");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler,4096,HttpParser.Compliance.RFC2616); HttpParser parser= new HttpParser(handler,4096,HttpCompliance.RFC2616);
parseAll(parser,buffer); parseAll(parser,buffer);
Assert.assertThat(_bad,Matchers.nullValue()); Assert.assertThat(_bad,Matchers.nullValue());
@ -252,7 +282,7 @@ public class HttpParserTest
"\015\012"); "\015\012");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler,4096,HttpParser.Compliance.RFC7230); HttpParser parser= new HttpParser(handler,4096,HttpCompliance.RFC7230);
parseAll(parser,buffer); parseAll(parser,buffer);
Assert.assertThat(_bad,Matchers.notNullValue()); Assert.assertThat(_bad,Matchers.notNullValue());
@ -602,7 +632,7 @@ public class HttpParserTest
"cOnNeCtIoN: ClOsE\015\012"+ "cOnNeCtIoN: ClOsE\015\012"+
"\015\012"); "\015\012");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler,-1,HttpParser.Compliance.RFC7230); HttpParser parser= new HttpParser(handler,-1,HttpCompliance.RFC7230);
parseAll(parser,buffer); parseAll(parser,buffer);
assertNull(_bad); assertNull(_bad);
assertEquals("GET", _methodOrVersion); assertEquals("GET", _methodOrVersion);
@ -624,7 +654,7 @@ public class HttpParserTest
"cOnNeCtIoN: ClOsE\015\012"+ "cOnNeCtIoN: ClOsE\015\012"+
"\015\012"); "\015\012");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser= new HttpParser(handler,-1,HttpParser.Compliance.STRICT); HttpParser parser= new HttpParser(handler,-1,HttpCompliance.LEGACY);
parseAll(parser,buffer); parseAll(parser,buffer);
assertNull(_bad); assertNull(_bad);
assertEquals("gEt", _methodOrVersion); assertEquals("gEt", _methodOrVersion);

View File

@ -29,6 +29,7 @@
<Item> <Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory"> <New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config"><Ref refid="httpConfig" /></Arg> <Arg name="config"><Ref refid="httpConfig" /></Arg>
<Arg name="compliance"><Call class="org.eclipse.jetty.http.HttpCompliance" name="valueOf"><Arg><Property name="jetty.http.compliance" default="RFC7230"/></Arg></Call></Arg>
</New> </New>
</Item> </Item>
</Array> </Array>

View File

@ -21,6 +21,7 @@
<Arg> <Arg>
<New class="org.eclipse.jetty.server.HttpConnectionFactory"> <New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config"><Ref refid="sslHttpConfig" /></Arg> <Arg name="config"><Ref refid="sslHttpConfig" /></Arg>
<Arg name="compliance"><Call class="org.eclipse.jetty.http.HttpCompliance" name="valueOf"><Arg><Property name="jetty.http.compliance" default="RFC7230"/></Arg></Call></Arg>
</New> </New>
</Arg> </Arg>
</Call> </Call>

View File

@ -35,3 +35,6 @@ etc/jetty-http.xml
## Thread priority delta to give to acceptor threads ## Thread priority delta to give to acceptor threads
# jetty.http.acceptorPriorityDelta=0 # jetty.http.acceptorPriorityDelta=0
## HTTP Compliance: RFC7230, RFC2616, LEGACY
# jetty.http.compliance=RFC7230

View File

@ -736,12 +736,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Commit failed", x); LOG.debug("Commit failed", x);
if (x instanceof EofException || x instanceof ClosedChannelException) if (x instanceof BadMessageException)
{
_callback.failed(x);
_response.getHttpOutput().closed();
}
else
{ {
_transport.send(HttpGenerator.RESPONSE_500_INFO, false, null, true, new Callback() _transport.send(HttpGenerator.RESPONSE_500_INFO, false, null, true, new Callback()
{ {
@ -755,11 +750,16 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
@Override @Override
public void failed(Throwable th) public void failed(Throwable th)
{ {
_transport.abort(x);
_callback.failed(x); _callback.failed(x);
_response.getHttpOutput().closed();
} }
}); });
} }
else
{
_transport.abort(x);
_callback.failed(x);
}
} }
} }

View File

@ -260,6 +260,11 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
switch (_metadata.getVersion()) switch (_metadata.getVersion())
{ {
case HTTP_0_9:
{
persistent=false;
break;
}
case HTTP_1_0: case HTTP_1_0:
{ {
if (getHttpConfiguration().isPersistentConnectionsEnabled()) if (getHttpConfiguration().isPersistentConnectionsEnabled())
@ -337,7 +342,7 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
default: default:
{ {
throw new IllegalStateException(); throw new IllegalStateException("unsupported version "+_metadata.getVersion());
} }
} }

View File

@ -24,6 +24,7 @@ import java.nio.channels.WritePendingException;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
@ -90,7 +91,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
return last; return last;
} }
public HttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint, HttpParser.Compliance compliance) public HttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint, HttpCompliance compliance)
{ {
super(endPoint, connector.getExecutor()); super(endPoint, connector.getExecutor());
_config = config; _config = config;
@ -119,7 +120,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
return new HttpChannelOverHttp(this, _connector, _config, getEndPoint(), this); return new HttpChannelOverHttp(this, _connector, _config, getEndPoint(), this);
} }
protected HttpParser newHttpParser(HttpParser.Compliance compliance) protected HttpParser newHttpParser(HttpCompliance compliance)
{ {
return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize(), compliance); return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize(), compliance);
} }

View File

@ -18,7 +18,7 @@
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
@ -32,17 +32,23 @@ import org.eclipse.jetty.util.annotation.Name;
public class HttpConnectionFactory extends AbstractConnectionFactory implements HttpConfiguration.ConnectionFactory public class HttpConnectionFactory extends AbstractConnectionFactory implements HttpConfiguration.ConnectionFactory
{ {
private final HttpConfiguration _config; private final HttpConfiguration _config;
private HttpParser.Compliance _httpCompliance=HttpParser.Compliance.RFC7230; private HttpCompliance _httpCompliance;
public HttpConnectionFactory() public HttpConnectionFactory()
{ {
this(new HttpConfiguration()); this(new HttpConfiguration());
} }
public HttpConnectionFactory(@Name("config") HttpConfiguration config) public HttpConnectionFactory(@Name("config") HttpConfiguration config)
{
this(config,null);
}
public HttpConnectionFactory(@Name("config") HttpConfiguration config, @Name("compliance") HttpCompliance compliance)
{ {
super(HttpVersion.HTTP_1_1.asString()); super(HttpVersion.HTTP_1_1.asString());
_config=config; _config=config;
_httpCompliance=compliance==null?HttpCompliance.RFC7230:compliance;
if (config==null) if (config==null)
throw new IllegalArgumentException("Null HttpConfiguration"); throw new IllegalArgumentException("Null HttpConfiguration");
addBean(_config); addBean(_config);
@ -54,15 +60,15 @@ public class HttpConnectionFactory extends AbstractConnectionFactory implements
return _config; return _config;
} }
public HttpParser.Compliance getHttpCompliance() public HttpCompliance getHttpCompliance()
{ {
return _httpCompliance; return _httpCompliance;
} }
/** /**
* @param httpCompliance String value of {@link HttpParser.Compliance} * @param httpCompliance String value of {@link HttpCompliance}
*/ */
public void setHttpCompliance(HttpParser.Compliance httpCompliance) public void setHttpCompliance(HttpCompliance httpCompliance)
{ {
_httpCompliance = httpCompliance; _httpCompliance = httpCompliance;
} }

View File

@ -447,11 +447,9 @@ public class HttpOutput extends ServletOutputStream implements Runnable
// write any remaining content in the buffer directly // write any remaining content in the buffer directly
if (len>0) if (len>0)
{ {
ByteBuffer wrap = ByteBuffer.wrap(b, off, len);
ByteBuffer view = wrap.duplicate();
// write a buffer capacity at a time to avoid JVM pooling large direct buffers // write a buffer capacity at a time to avoid JVM pooling large direct buffers
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6210541 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6210541
ByteBuffer view = ByteBuffer.wrap(b, off, len);
while (len>getBufferSize()) while (len>getBufferSize())
{ {
int p=view.position(); int p=view.position();

View File

@ -28,19 +28,21 @@ import org.eclipse.jetty.util.component.LifeCycle;
*/ */
public interface SessionIdManager extends LifeCycle public interface SessionIdManager extends LifeCycle
{ {
/* ------------------------------------------------------------ */
/** /**
* @param id The plain session ID (ie no workername extension) * @param id The plain session ID (ie no workername extension)
* @return True if the session ID is in use by at least one context. * @return True if the session ID is in use by at least one context.
*/ */
public boolean isIdInUse(String id); public boolean isIdInUse(String id);
/* ------------------------------------------------------------ */
/** /**
* Notify the sessionid manager that a particular session id is in use * Notify the sessionid manager that a particular session id is in use
* @param the session whose id is being used * @param session the session whose id is being used
*/ */
public void useId (Session session); public void useId (Session session);
/* ------------------------------------------------------------ */
/** /**
* Remove id * Remove id
* @param id the plain session id (no workername extension) of the session to remove * @param id the plain session id (no workername extension) of the session to remove
@ -48,6 +50,8 @@ public interface SessionIdManager extends LifeCycle
*/ */
public boolean removeId (String id); public boolean removeId (String id);
/* ------------------------------------------------------------ */
/** /**
* Invalidate all sessions on all contexts that share the same id. * Invalidate all sessions on all contexts that share the same id.
* *
@ -55,6 +59,7 @@ public interface SessionIdManager extends LifeCycle
*/ */
public void expireAll(String id); public void expireAll(String id);
/* ------------------------------------------------------------ */
/** /**
* Create a new Session ID. * Create a new Session ID.
* *
@ -65,7 +70,10 @@ public interface SessionIdManager extends LifeCycle
public String newSessionId(HttpServletRequest request,long created); public String newSessionId(HttpServletRequest request,long created);
/* ------------------------------------------------------------ */
/**
* @return the unique name of this server instance
*/
public String getWorkerName(); public String getWorkerName();

View File

@ -32,11 +32,22 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
protected SessionContext _context; //context associated with this session data store protected SessionContext _context; //context associated with this session data store
/**
* Store the session data persistently.
*
* @param id identity of session to store
* @param data info of the session
* @param isNew has session been written out before or not
* @throws Exception
*/
public abstract void doStore(String id, SessionData data, boolean isNew) throws Exception; public abstract void doStore(String id, SessionData data, boolean isNew) throws Exception;
/**
* @see org.eclipse.jetty.server.session.SessionDataStore#initialize(org.eclipse.jetty.server.session.SessionContext)
*/
public void initialize (SessionContext context) public void initialize (SessionContext context)
{ {
if (isStarted()) if (isStarted())
@ -69,8 +80,9 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.SessionKey, long, long, long, long) * @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(java.lang.String, long, long, long, long)
*/ */
@Override @Override
public SessionData newSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs) public SessionData newSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs)
@ -78,6 +90,9 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
return new SessionData(id, _context.getCanonicalContextPath(), _context.getVhost(), created, accessed, lastAccessed, maxInactiveMs); return new SessionData(id, _context.getCanonicalContextPath(), _context.getVhost(), created, accessed, lastAccessed, maxInactiveMs);
} }
/**
* @throws IllegalStateException
*/
protected void checkStarted () throws IllegalStateException protected void checkStarted () throws IllegalStateException
{ {
if (isStarted()) if (isStarted())

View File

@ -58,12 +58,19 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
protected SessionScavenger _scavenger; protected SessionScavenger _scavenger;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @param server the server associated with the id manager
*/
public AbstractSessionIdManager(Server server) public AbstractSessionIdManager(Server server)
{ {
_server = server; _server = server;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @param server the server associated with the id manager
* @param random a random number generator to use for ids
*/
public AbstractSessionIdManager(Server server, Random random) public AbstractSessionIdManager(Server server, Random random)
{ {
this(server); this(server);
@ -71,6 +78,9 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @param server the server associated with this id manager
*/
public void setServer (Server server) public void setServer (Server server)
{ {
_server = server; _server = server;
@ -78,7 +88,9 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @return the server associated with this id manager
*/
public Server getServer () public Server getServer ()
{ {
return _server; return _server;
@ -88,7 +100,7 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param scavenger * @param scavenger a SessionScavenger
*/ */
public void setSessionScavenger (SessionScavenger scavenger) public void setSessionScavenger (SessionScavenger scavenger)
{ {
@ -103,7 +115,7 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
* Get the workname. If set, the workername is dot appended to the session * Get the workname. If set, the workername is dot appended to the session
* ID and can be used to assist session affinity in a load balancer. * ID and can be used to assist session affinity in a load balancer.
* *
* @return String or null * @return name or null
*/ */
@Override @Override
public String getWorkerName() public String getWorkerName()
@ -133,12 +145,18 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @return the random number generator
*/
public Random getRandom() public Random getRandom()
{ {
return _random; return _random;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @param random a random number generator for generating ids
*/
public synchronized void setRandom(Random random) public synchronized void setRandom(Random random)
{ {
_random=random; _random=random;
@ -166,7 +184,7 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Create a new session id if necessary. * Create a new session id if necessary.
* *
* @see org.eclipse.jetty.server.SessionIdManager#newSessionId(javax.servlet.http.HttpServletRequest, long) * @see org.eclipse.jetty.server.SessionIdManager#newSessionId(javax.servlet.http.HttpServletRequest, long)
*/ */
@Override @Override
@ -200,6 +218,10 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @param seedTerm
* @return a new unique session id
*/
public String newSessionId(long seedTerm) public String newSessionId(long seedTerm)
{ {
// pick a new unique ID! // pick a new unique ID!
@ -249,6 +271,9 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
@ -268,6 +293,9 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
*/
@Override @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
@ -418,7 +446,7 @@ public abstract class AbstractSessionIdManager extends AbstractLifeCycle impleme
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Get SessionManager for every context. /** Get SessionManager for every context.
* *
* @return * @return all session managers
*/ */
protected Set<SessionManager> getSessionManagers() protected Set<SessionManager> getSessionManagers()
{ {

View File

@ -50,7 +50,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/** /**
* Create a new Session object from session data * Create a new Session object from session data
* @param data * @param data
* @return * @return a new Session object
*/ */
public abstract Session newSession (SessionData data); public abstract Session newSession (SessionData data);
@ -59,7 +59,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/** /**
* Get the session matching the key * Get the session matching the key
* @param id session id * @param id session id
* @return * @return the Session object matching the id
*/ */
public abstract Session doGet(String id); public abstract Session doGet(String id);
@ -79,7 +79,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/** /**
* Check to see if the session exists in the store * Check to see if the session exists in the store
* @param id * @param id
* @return * @return true if the Session object exists in the session store
*/ */
public abstract boolean doExists (String id); public abstract boolean doExists (String id);
@ -97,7 +97,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/** /**
* Get a list of keys for sessions that the store thinks has expired * Get a list of keys for sessions that the store thinks has expired
* @return * @return ids of all Session objects that might have expired
*/ */
public abstract Set<String> doGetExpiredCandidates(); public abstract Set<String> doGetExpiredCandidates();
@ -112,11 +112,17 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
} }
/**
* @param manager
*/
public void setSessionManager (SessionManager manager) public void setSessionManager (SessionManager manager)
{ {
_manager = manager; _manager = manager;
} }
/**
* @return the SessionManger
*/
public SessionManager getSessionManager() public SessionManager getSessionManager()
{ {
return _manager; return _manager;
@ -124,6 +130,9 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/**
* @see org.eclipse.jetty.server.session.SessionStore#initialize(org.eclipse.jetty.server.session.SessionContext)
*/
public void initialize (SessionContext context) public void initialize (SessionContext context)
{ {
if (isStarted()) if (isStarted())
@ -131,6 +140,9 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
_context = context; _context = context;
} }
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
{ {
@ -149,6 +161,9 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
super.doStart(); super.doStart();
} }
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
*/
@Override @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {
@ -156,34 +171,47 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
super.doStop(); super.doStop();
} }
/**
* @return the SessionDataStore or null if there isn't one
*/
public SessionDataStore getSessionDataStore() public SessionDataStore getSessionDataStore()
{ {
return _sessionDataStore; return _sessionDataStore;
} }
/**
* @param sessionDataStore
*/
public void setSessionDataStore(SessionDataStore sessionDataStore) public void setSessionDataStore(SessionDataStore sessionDataStore)
{ {
_sessionDataStore = sessionDataStore; _sessionDataStore = sessionDataStore;
} }
/**
* @return the strategy for detecting stale sessions or null if there isn't one
*/
public StalenessStrategy getStaleStrategy() public StalenessStrategy getStaleStrategy()
{ {
return _staleStrategy; return _staleStrategy;
} }
/**
* @param staleStrategy
*/
public void setStaleStrategy(StalenessStrategy staleStrategy) public void setStaleStrategy(StalenessStrategy staleStrategy)
{ {
_staleStrategy = staleStrategy; _staleStrategy = staleStrategy;
} }
/** /**
* Get a session object. * Get a session object.
* *
* If the session object is not in this session store, try getting * If the session object is not in this session store, try getting
* the data for it from a SessionDataStore associated with the * the data for it from a SessionDataStore associated with the
* session manager. * session manager.
* *
* @see org.eclipse.jetty.server.session.SessionStore#get(java.lang.String) * @see org.eclipse.jetty.server.session.SessionStore#get(java.lang.String, boolean)
*/ */
@Override @Override
public Session get(String id, boolean staleCheck) throws Exception public Session get(String id, boolean staleCheck) throws Exception
@ -292,7 +320,7 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/** /**
* @param session * @param session
* @return * @return true or false according to the StaleStrategy
*/ */
public boolean isStale (Session session) public boolean isStale (Session session)
{ {
@ -319,6 +347,9 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
/**
* @see org.eclipse.jetty.server.session.SessionStore#newSession(javax.servlet.http.HttpServletRequest, java.lang.String, long, long)
*/
@Override @Override
public Session newSession(HttpServletRequest request, String id, long time, long maxInactiveMs) public Session newSession(HttpServletRequest request, String id, long time, long maxInactiveMs)
{ {

View File

@ -74,7 +74,7 @@ public class CachingSessionDataStore extends AbstractSessionDataStore
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#load(org.eclipse.jetty.server.session.SessionKey) * @see org.eclipse.jetty.server.session.SessionDataStore#load(java.lang.String)
*/ */
@Override @Override
public SessionData load(String id) throws Exception public SessionData load(String id) throws Exception
@ -101,8 +101,9 @@ public class CachingSessionDataStore extends AbstractSessionDataStore
return d; return d;
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#delete(org.eclipse.jetty.server.session.SessionKey) * @see org.eclipse.jetty.server.session.SessionDataStore#delete(java.lang.String)
*/ */
@Override @Override
public boolean delete(String id) throws Exception public boolean delete(String id) throws Exception
@ -124,8 +125,9 @@ public class CachingSessionDataStore extends AbstractSessionDataStore
return null; return null;
} }
/** /**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(org.eclipse.jetty.server.session.SessionKey, org.eclipse.jetty.server.session.SessionData, boolean) * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(java.lang.String, org.eclipse.jetty.server.session.SessionData, boolean)
*/ */
@Override @Override
public void doStore(String id, SessionData data, boolean isNew) throws Exception public void doStore(String id, SessionData data, boolean isNew) throws Exception

View File

@ -88,8 +88,9 @@ public class FileSessionDataStore extends AbstractSessionDataStore
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#delete(org.eclipse.jetty.server.session.SessionKey) * @see org.eclipse.jetty.server.session.SessionDataStore#delete(java.lang.String)
*/ */
@Override @Override
public boolean delete(String id) throws Exception public boolean delete(String id) throws Exception
@ -108,8 +109,9 @@ public class FileSessionDataStore extends AbstractSessionDataStore
return false; return false;
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired() * @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/ */
@Override @Override
public Set<String> getExpired(Set<String> candidates) public Set<String> getExpired(Set<String> candidates)
@ -119,8 +121,9 @@ public class FileSessionDataStore extends AbstractSessionDataStore
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#load(org.eclipse.jetty.server.session.SessionKey) * @see org.eclipse.jetty.server.session.SessionDataStore#load(java.lang.String)
*/ */
@Override @Override
public SessionData load(String id) throws Exception public SessionData load(String id) throws Exception
@ -173,9 +176,8 @@ public class FileSessionDataStore extends AbstractSessionDataStore
/** /**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(org.eclipse.jetty.server.session.SessionKey, org.eclipse.jetty.server.session.SessionData) * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(java.lang.String, org.eclipse.jetty.server.session.SessionData, boolean)
*/ */
@Override @Override
public void doStore(String id, SessionData data, boolean isNew) throws Exception public void doStore(String id, SessionData data, boolean isNew) throws Exception
@ -200,6 +202,9 @@ public class FileSessionDataStore extends AbstractSessionDataStore
} }
} }
/**
*
*/
public void initializeStore () public void initializeStore ()
{ {
if (_storeDir == null) if (_storeDir == null)
@ -219,6 +224,12 @@ public class FileSessionDataStore extends AbstractSessionDataStore
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/**
* @param os the output stream to save to
* @param id identity of the session
* @param data the info of the session
* @throws IOException
*/
private void save(OutputStream os, String id, SessionData data) throws IOException private void save(OutputStream os, String id, SessionData data) throws IOException
{ {
DataOutputStream out = new DataOutputStream(os); DataOutputStream out = new DataOutputStream(os);
@ -243,12 +254,21 @@ public class FileSessionDataStore extends AbstractSessionDataStore
} }
} }
/**
* @param id identity of session
* @return
*/
private String getFileName (String id) private String getFileName (String id)
{ {
return _context.getCanonicalContextPath()+"_"+_context.getVhost()+"_"+id; return _context.getCanonicalContextPath()+"_"+_context.getVhost()+"_"+id;
} }
/**
* @param is inputstream containing session data
* @return
* @throws Exception
*/
private SessionData load (InputStream is) private SessionData load (InputStream is)
throws Exception throws Exception
{ {
@ -289,6 +309,12 @@ public class FileSessionDataStore extends AbstractSessionDataStore
} }
} }
/**
* @param is inputstream containing session data
* @param size number of attributes
* @param data the data to restore to
* @throws Exception
*/
private void restoreAttributes (InputStream is, int size, SessionData data) private void restoreAttributes (InputStream is, int size, SessionData data)
throws Exception throws Exception
{ {

View File

@ -54,8 +54,7 @@ public class HashSessionIdManager extends AbstractSessionIdManager
/** /**
* @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String) * @see org.eclipse.jetty.server.SessionIdManager#useId(org.eclipse.jetty.server.session.Session)
* @param session the session whose id to use
*/ */
@Override @Override
public void useId(Session session) public void useId(Session session)

View File

@ -630,7 +630,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#load(org.eclipse.jetty.server.session.SessionKey) * @see org.eclipse.jetty.server.session.SessionDataStore#load(java.lang.String)
*/ */
@Override @Override
public SessionData load(String id) throws Exception public SessionData load(String id) throws Exception
@ -748,7 +748,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
/** /**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore() * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(java.lang.String, org.eclipse.jetty.server.session.SessionData, boolean)
*/ */
@Override @Override
public void doStore(String id, SessionData data, boolean isNew) throws Exception public void doStore(String id, SessionData data, boolean isNew) throws Exception
@ -849,8 +849,9 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired() * @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/ */
@Override @Override
public Set<String> getExpired(Set<String> candidates) public Set<String> getExpired(Set<String> candidates)

View File

@ -160,10 +160,9 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
/** /**
* Record the session id as being in use * @see org.eclipse.jetty.server.SessionIdManager#useId(org.eclipse.jetty.server.session.Session)
*
* @see org.eclipse.jetty.server.SessionIdManager#useId(java.lang.String)
*/ */
@Override @Override
public void useId (Session session) public void useId (Session session)
@ -225,7 +224,7 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
/** /**
* Insert a new used session id into the table. * Insert a new used session id into the table.
* *
* @param id * @param id the id to put into the table
* @throws SQLException * @throws SQLException
*/ */
private void insert (String id) private void insert (String id)
@ -254,7 +253,7 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
/** /**
* Remove a session id from the table. * Remove a session id from the table.
* *
* @param id * @param id the id to remove from the table
* @throws SQLException * @throws SQLException
*/ */
private boolean delete (String id) private boolean delete (String id)
@ -273,8 +272,8 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
/** /**
* Check if a session id exists. * Check if a session id exists.
* *
* @param id * @param id the id to check
* @return * @return true if the id exists in the table, false otherwise
* @throws SQLException * @throws SQLException
*/ */
private boolean exists (String id) private boolean exists (String id)
@ -350,7 +349,7 @@ public class JDBCSessionIdManager extends org.eclipse.jetty.server.session.Abstr
/** /**
* Get the database adaptor in order to configure it * Get the database adaptor in order to configure it
* @return * @return the database adpator
*/ */
public DatabaseAdaptor getDatabaseAdaptor () public DatabaseAdaptor getDatabaseAdaptor ()
{ {

View File

@ -51,11 +51,9 @@ public class MemorySessionStore extends AbstractSessionStore
*/ */
public class MemorySession extends Session public class MemorySession extends Session
{ {
/** /**
* @param manager * @param request the request associated with the new session
* @param request * @param data the info for the session
* @param data
*/ */
public MemorySession(HttpServletRequest request, SessionData data) public MemorySession(HttpServletRequest request, SessionData data)
{ {
@ -63,11 +61,8 @@ public class MemorySessionStore extends AbstractSessionStore
} }
/** /**
* @param manager * @param data the info for the restored session object
* @param data
*/ */
public MemorySession(SessionData data) public MemorySession(SessionData data)
{ {
@ -222,8 +217,9 @@ public class MemorySessionStore extends AbstractSessionStore
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionStore#newSession(java.lang.String) * @see org.eclipse.jetty.server.session.AbstractSessionStore#newSession(javax.servlet.http.HttpServletRequest, java.lang.String, long, long)
*/ */
@Override @Override
public Session newSession(HttpServletRequest request, String id, long time, long maxInactiveMs) public Session newSession(HttpServletRequest request, String id, long time, long maxInactiveMs)

View File

@ -38,9 +38,9 @@ public class NullSessionDataStore extends AbstractSessionDataStore
return null; return null;
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#newSessionData(org.eclipse.jetty.server.session.SessionKey, long, long, long, long) * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#newSessionData(java.lang.String, long, long, long, long)
*/ */
@Override @Override
public SessionData newSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs) public SessionData newSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs)
@ -57,8 +57,9 @@ public class NullSessionDataStore extends AbstractSessionDataStore
return true; return true;
} }
/** /**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore() * @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(java.lang.String, org.eclipse.jetty.server.session.SessionData, boolean)
*/ */
@Override @Override
public void doStore(String id, SessionData data, boolean isNew) throws Exception public void doStore(String id, SessionData data, boolean isNew) throws Exception
@ -66,8 +67,9 @@ public class NullSessionDataStore extends AbstractSessionDataStore
//noop //noop
} }
/** /**
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired() * @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(java.util.Set)
*/ */
@Override @Override
public Set<String> getExpired(Set<String> candidates) public Set<String> getExpired(Set<String> candidates)

View File

@ -755,7 +755,7 @@ public class Session implements SessionManager.SessionIf
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/** /**
* @see org.eclipse.jetty.server.session.AbstractSessionManager.SessionIf#getSession() * @see org.eclipse.jetty.server.session.SessionManager.SessionIf#getSession()
*/ */
@Override @Override
public Session getSession() public Session getSession()

View File

@ -84,6 +84,9 @@ public class SessionData implements Serializable
} }
/**
* @return time at which session was last written out
*/
public long getLastSaved() public long getLastSaved()
{ {
return _lastSaved; return _lastSaved;
@ -91,32 +94,53 @@ public class SessionData implements Serializable
/**
* @param lastSaved
*/
public void setLastSaved(long lastSaved) public void setLastSaved(long lastSaved)
{ {
_lastSaved = lastSaved; _lastSaved = lastSaved;
} }
/**
* @return true if a session needs to be written out
*/
public boolean isDirty() public boolean isDirty()
{ {
return _dirty; return _dirty;
} }
/**
* @param dirty
*/
public void setDirty(boolean dirty) public void setDirty(boolean dirty)
{ {
_dirty = dirty; _dirty = dirty;
} }
/**
* @param name
* @return the value of the attribute named
*/
public Object getAttribute (String name) public Object getAttribute (String name)
{ {
return _attributes.get(name); return _attributes.get(name);
} }
/**
* @return a Set of attribute names
*/
public Set<String> getKeys() public Set<String> getKeys()
{ {
return _attributes.keySet(); return _attributes.keySet();
} }
/**
* @param name
* @param value
* @return
*/
public Object setAttribute (String name, Object value) public Object setAttribute (String name, Object value)
{ {
Object old = (value==null?_attributes.remove(name):_attributes.put(name,value)); Object old = (value==null?_attributes.remove(name):_attributes.put(name,value));
@ -128,6 +152,9 @@ public class SessionData implements Serializable
} }
/**
* @param name
*/
public void setDirty (String name) public void setDirty (String name)
{ {
setDirty (true); setDirty (true);
@ -135,101 +162,161 @@ public class SessionData implements Serializable
/**
* @param attributes
*/
public void putAllAttributes (Map<String,Object> attributes) public void putAllAttributes (Map<String,Object> attributes)
{ {
_attributes.putAll(attributes); _attributes.putAll(attributes);
} }
/**
* @return an unmodifiable map of the attributes
*/
public Map<String,Object> getAllAttributes() public Map<String,Object> getAllAttributes()
{ {
return Collections.unmodifiableMap(_attributes); return Collections.unmodifiableMap(_attributes);
} }
/**
* @return the id of the session
*/
public String getId() public String getId()
{ {
return _id; return _id;
} }
/**
* @param id
*/
public void setId(String id) public void setId(String id)
{ {
_id = id; _id = id;
} }
/**
* @return the context path associated with this session
*/
public String getContextPath() public String getContextPath()
{ {
return _contextPath; return _contextPath;
} }
/**
* @param contextPath
*/
public void setContextPath(String contextPath) public void setContextPath(String contextPath)
{ {
_contextPath = contextPath; _contextPath = contextPath;
} }
/**
* @return virtual host of context associated with session
*/
public String getVhost() public String getVhost()
{ {
return _vhost; return _vhost;
} }
/**
* @param vhost
*/
public void setVhost(String vhost) public void setVhost(String vhost)
{ {
_vhost = vhost; _vhost = vhost;
} }
/**
* @return last node to manage the session
*/
public String getLastNode() public String getLastNode()
{ {
return _lastNode; return _lastNode;
} }
/**
* @param lastNode
*/
public void setLastNode(String lastNode) public void setLastNode(String lastNode)
{ {
_lastNode = lastNode; _lastNode = lastNode;
} }
/**
* @return time at which session expires
*/
public long getExpiry() public long getExpiry()
{ {
return _expiry; return _expiry;
} }
/**
* @param expiry
*/
public void setExpiry(long expiry) public void setExpiry(long expiry)
{ {
_expiry = expiry; _expiry = expiry;
} }
/**
* @return
*/
public long getCreated() public long getCreated()
{ {
return _created; return _created;
} }
/**
* @param created
*/
public void setCreated(long created) public void setCreated(long created)
{ {
_created = created; _created = created;
} }
/**
* @return time cookie was set
*/
public long getCookieSet() public long getCookieSet()
{ {
return _cookieSet; return _cookieSet;
} }
/**
* @param cookieSet
*/
public void setCookieSet(long cookieSet) public void setCookieSet(long cookieSet)
{ {
_cookieSet = cookieSet; _cookieSet = cookieSet;
} }
/**
* @return time session was accessed
*/
public long getAccessed() public long getAccessed()
{ {
return _accessed; return _accessed;
} }
/**
* @param accessed
*/
public void setAccessed(long accessed) public void setAccessed(long accessed)
{ {
_accessed = accessed; _accessed = accessed;
} }
/**
* @return previous time session was accessed
*/
public long getLastAccessed() public long getLastAccessed()
{ {
return _lastAccessed; return _lastAccessed;
} }
/**
* @param lastAccessed
*/
public void setLastAccessed(long lastAccessed) public void setLastAccessed(long lastAccessed)
{ {
_lastAccessed = lastAccessed; _lastAccessed = lastAccessed;
@ -242,16 +329,26 @@ public class SessionData implements Serializable
*/ */
/**
* @return
*/
public long getMaxInactiveMs() public long getMaxInactiveMs()
{ {
return _maxInactiveMs; return _maxInactiveMs;
} }
/**
* @param maxInactive
*/
public void setMaxInactiveMs(long maxInactive) public void setMaxInactiveMs(long maxInactive)
{ {
_maxInactiveMs = maxInactive; _maxInactiveMs = maxInactive;
} }
/**
* @param out
* @throws IOException
*/
private void writeObject(java.io.ObjectOutputStream out) throws IOException private void writeObject(java.io.ObjectOutputStream out) throws IOException
{ {
out.writeUTF(_id); //session id out.writeUTF(_id); //session id
@ -269,6 +366,11 @@ public class SessionData implements Serializable
out.writeObject(_attributes); out.writeObject(_attributes);
} }
/**
* @param in
* @throws IOException
* @throws ClassNotFoundException
*/
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
{ {
_id = in.readUTF(); _id = in.readUTF();
@ -286,6 +388,10 @@ public class SessionData implements Serializable
} }
/**
* @param time
* @return
*/
public boolean isExpiredAt (long time) public boolean isExpiredAt (long time)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())

View File

@ -36,7 +36,7 @@ public interface SessionDataStore extends LifeCycle
* given context. A SessionDataStore can only * given context. A SessionDataStore can only
* be used by one context(/session manager). * be used by one context(/session manager).
* *
* @param context * @param context context associated
*/ */
void initialize(SessionContext context); void initialize(SessionContext context);
@ -44,8 +44,8 @@ public interface SessionDataStore extends LifeCycle
/** /**
* Read in session data from storage * Read in session data from storage
* @param id * @param id identity of session to load
* @return * @return the SessionData matching the id
* @throws Exception * @throws Exception
*/ */
public SessionData load (String id) throws Exception; public SessionData load (String id) throws Exception;
@ -53,7 +53,12 @@ public interface SessionDataStore extends LifeCycle
/** /**
* Create a new SessionData * Create a new SessionData
* @return * @param id
* @param created
* @param accessed
* @param lastAccessed
* @param maxInactiveMs
* @return a new SessionData object
*/ */
public SessionData newSessionData (String id, long created, long accessed, long lastAccessed, long maxInactiveMs); public SessionData newSessionData (String id, long created, long accessed, long lastAccessed, long maxInactiveMs);
@ -62,8 +67,8 @@ public interface SessionDataStore extends LifeCycle
/** /**
* Write out session data to storage * Write out session data to storage
* @param id * @param id identity of session to store
* @param data * @param data info of session to store
* @throws Exception * @throws Exception
*/ */
public void store (String id, SessionData data) throws Exception; public void store (String id, SessionData data) throws Exception;
@ -72,8 +77,8 @@ public interface SessionDataStore extends LifeCycle
/** /**
* Delete session data from storage * Delete session data from storage
* @param id * @param id identity of session to delete
* @return * @return true if the session was deleted from the permanent store
* @throws Exception * @throws Exception
*/ */
public boolean delete (String id) throws Exception; public boolean delete (String id) throws Exception;
@ -88,7 +93,7 @@ public interface SessionDataStore extends LifeCycle
* @param candidates if provided, these are keys of sessions that * @param candidates if provided, these are keys of sessions that
* the SessionStore thinks has expired and should be verified by the * the SessionStore thinks has expired and should be verified by the
* SessionDataStore * SessionDataStore
* @return * @return set of session ids
*/ */
public Set<String> getExpired (Set<String> candidates); public Set<String> getExpired (Set<String> candidates);
@ -96,7 +101,7 @@ public interface SessionDataStore extends LifeCycle
/** /**
* True if this type of datastore will passivate session objects * True if this type of datastore will passivate session objects
* @return * @return true if this store can passivate sessions, false otherwise
*/ */
public boolean isPassivating (); public boolean isPassivating ();

View File

@ -29,7 +29,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ChannelEndPoint; import org.eclipse.jetty.io.ChannelEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
@ -94,7 +94,7 @@ public class ExtendedServerTest extends HttpServerTestBase
private static class ExtendedHttpConnection extends HttpConnection private static class ExtendedHttpConnection extends HttpConnection
{ {
public ExtendedHttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint, HttpParser.Compliance compliance) public ExtendedHttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint, HttpCompliance compliance)
{ {
super(config,connector,endPoint,compliance); super(config,connector,endPoint,compliance);
} }

View File

@ -42,6 +42,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpCompliance;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.MimeTypes;
@ -236,6 +237,18 @@ public class HttpConnectionTest
checkContains(response,0,"HTTP/1.1 400 Bad URI"); checkContains(response,0,"HTTP/1.1 400 Bad URI");
} }
@Test
public void test_0_9() throws Exception
{
connector.getConnectionFactory(HttpConnectionFactory.class).setHttpCompliance(HttpCompliance.RFC2616);
String response=connector.getResponses("GET /R1\n");
int offset=0;
checkNotContained(response,offset,"HTTP/1.1");
checkNotContained(response,offset,"200");
checkContains(response,offset,"pathInfo=/R1");
}
@Test @Test
public void testSimple() throws Exception public void testSimple() throws Exception
{ {