Merged branch 'jetty-9.3.x' into 'master'.
This commit is contained in:
commit
51009208d4
|
@ -23,8 +23,8 @@ import java.net.HttpCookie;
|
|||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.client.api.Authentication;
|
||||
import org.eclipse.jetty.client.api.Connection;
|
||||
|
@ -45,12 +45,14 @@ public abstract class HttpConnection implements Connection
|
|||
private static final Logger LOG = Log.getLogger(HttpConnection.class);
|
||||
private static final HttpField CHUNKED_FIELD = new HttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED);
|
||||
|
||||
private final AtomicInteger idleTimeoutState = new AtomicInteger();
|
||||
private final HttpDestination destination;
|
||||
private int idleTimeoutGuard;
|
||||
private long idleTimeoutStamp;
|
||||
|
||||
protected HttpConnection(HttpDestination destination)
|
||||
{
|
||||
this.destination = destination;
|
||||
this.idleTimeoutStamp = System.nanoTime();
|
||||
}
|
||||
|
||||
public HttpClient getHttpClient()
|
||||
|
@ -180,17 +182,12 @@ public abstract class HttpConnection implements Connection
|
|||
// Forbid idle timeouts for the time window where
|
||||
// the request is associated to the channel and sent.
|
||||
// Use a counter to support multiplexed requests.
|
||||
boolean send = false;
|
||||
while (true)
|
||||
boolean send;
|
||||
synchronized (this)
|
||||
{
|
||||
int current = idleTimeoutState.get();
|
||||
if (current < 0)
|
||||
break;
|
||||
if (idleTimeoutState.compareAndSet(current, current + 1))
|
||||
{
|
||||
send = true;
|
||||
break;
|
||||
}
|
||||
send = idleTimeoutGuard >= 0;
|
||||
if (send)
|
||||
++idleTimeoutGuard;
|
||||
}
|
||||
|
||||
if (send)
|
||||
|
@ -207,7 +204,13 @@ public abstract class HttpConnection implements Connection
|
|||
channel.release();
|
||||
result = new SendFailure(new HttpRequestException("Could not associate request to connection", request), false);
|
||||
}
|
||||
idleTimeoutState.decrementAndGet();
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
--idleTimeoutGuard;
|
||||
idleTimeoutStamp = System.nanoTime();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
|
@ -216,11 +219,27 @@ public abstract class HttpConnection implements Connection
|
|||
}
|
||||
}
|
||||
|
||||
public boolean onIdleTimeout()
|
||||
public boolean onIdleTimeout(long idleTimeout)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Idle timeout state {} - {}", idleTimeoutState, this);
|
||||
return idleTimeoutState.compareAndSet(0, -1);
|
||||
synchronized (this)
|
||||
{
|
||||
if (idleTimeoutGuard == 0)
|
||||
{
|
||||
long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - idleTimeoutStamp);
|
||||
boolean idle = elapsed > idleTimeout / 2;
|
||||
if (idle)
|
||||
idleTimeoutGuard = -1;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Idle timeout {}/{}ms - {}", elapsed, idleTimeout, this);
|
||||
return idle;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Idle timeout skipped - {}", this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -459,7 +459,7 @@ public abstract class HttpDestination extends ContainerLifeCycle implements Dest
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[%s]%x%s,queue=%d,pool=%s",
|
||||
return String.format("%s[%s]@%x%s,queue=%d,pool=%s",
|
||||
HttpDestination.class.getSimpleName(),
|
||||
asString(),
|
||||
hashCode(),
|
||||
|
|
|
@ -99,9 +99,10 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
|
|||
@Override
|
||||
public boolean onIdleExpired()
|
||||
{
|
||||
boolean close = delegate.onIdleTimeout();
|
||||
long idleTimeout = getEndPoint().getIdleTimeout();
|
||||
boolean close = delegate.onIdleTimeout(idleTimeout);
|
||||
if (close)
|
||||
close(new TimeoutException("Idle timeout " + getEndPoint().getIdleTimeout() + "ms"));
|
||||
close(new TimeoutException("Idle timeout " + idleTimeout + "ms"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,9 @@ public class HttpReceiverOverHTTPTest
|
|||
HttpExchange exchange = newExchange();
|
||||
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
|
||||
connection.getHttpChannel().receive();
|
||||
// Simulate an idle timeout
|
||||
// ByteArrayEndPoint has an idle timeout of 0 by default,
|
||||
// so to simulate an idle timeout is enough to wait a bit.
|
||||
Thread.sleep(100);
|
||||
connection.onIdleExpired();
|
||||
|
||||
try
|
||||
|
|
|
@ -111,12 +111,12 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
return configure(new HttpConnection(getHttpConfiguration(), connector, endPoint)
|
||||
return configure(new HttpConnection(getHttpConfiguration(), connector, endPoint,getHttpCompliance())
|
||||
{
|
||||
@Override
|
||||
protected HttpParser newHttpParser()
|
||||
protected HttpParser newHttpParser(HttpParser.Compliance compliance)
|
||||
{
|
||||
return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize())
|
||||
return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize(),compliance)
|
||||
{
|
||||
@Override
|
||||
public boolean parseNext(ByteBuffer buffer)
|
||||
|
|
|
@ -18,19 +18,19 @@ NAME=$(echo $(basename $0) | sed -e 's/^[SK][0-9]*//' -e 's/\.sh$//')
|
|||
# Configuration files
|
||||
#
|
||||
# /etc/default/$NAME
|
||||
# If it exists, this is read at the start of script. It may perform any
|
||||
# If it exists, this is read at the start of script. It may perform any
|
||||
# sequence of shell commands, like setting relevant environment variables.
|
||||
#
|
||||
# $HOME/.$NAMErc (e.g. $HOME/.jettyrc)
|
||||
# If it exists, this is read at the start of script. It may perform any
|
||||
# If it exists, this is read at the start of script. It may perform any
|
||||
# sequence of shell commands, like setting relevant environment variables.
|
||||
#
|
||||
# /etc/$NAME.conf
|
||||
# If found, and no configurations were given on the command line,
|
||||
# the file will be used as this script's configuration.
|
||||
# the file will be used as this script's configuration.
|
||||
# Each line in the file may contain:
|
||||
# - A comment denoted by the pound (#) sign as first non-blank character.
|
||||
# - The path to a regular file, which will be passed to jetty as a
|
||||
# - The path to a regular file, which will be passed to jetty as a
|
||||
# config.xml file.
|
||||
# - The path to a directory. Each *.xml file in the directory will be
|
||||
# passed to jetty as a config.xml file.
|
||||
|
@ -62,10 +62,10 @@ NAME=$(echo $(basename $0) | sed -e 's/^[SK][0-9]*//' -e 's/\.sh$//')
|
|||
# Where the $NAME.pid file should be stored. It defaults to the
|
||||
# first available of /var/run, /usr/var/run, JETTY_BASE and /tmp
|
||||
# if not set.
|
||||
#
|
||||
#
|
||||
# JETTY_PID
|
||||
# The Jetty PID file, defaults to $JETTY_RUN/$NAME.pid
|
||||
#
|
||||
#
|
||||
# JETTY_ARGS
|
||||
# The default arguments to pass to jetty.
|
||||
# For example
|
||||
|
@ -97,10 +97,10 @@ findDirectory()
|
|||
local L OP=$1
|
||||
shift
|
||||
for L in "$@"; do
|
||||
[ "$OP" "$L" ] || continue
|
||||
[ "$OP" "$L" ] || continue
|
||||
printf %s "$L"
|
||||
break
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
running()
|
||||
|
@ -118,7 +118,7 @@ running()
|
|||
started()
|
||||
{
|
||||
# wait for 60s to see "STARTED" in PID file, needs jetty-started.xml as argument
|
||||
for T in 1 2 3 4 5 6 7 9 10 11 12 13 14 15
|
||||
for T in 1 2 3 4 5 6 7 9 10 11 12 13 14 15
|
||||
do
|
||||
sleep 4
|
||||
[ -z "$(grep STARTED $1 2>/dev/null)" ] || return 0
|
||||
|
@ -162,12 +162,12 @@ shift
|
|||
##################################################
|
||||
ETC=/etc
|
||||
if [ $UID != 0 ]
|
||||
then
|
||||
then
|
||||
ETC=$HOME/etc
|
||||
fi
|
||||
|
||||
for CONFIG in {/etc,~/etc}/default/${NAME}{,9} $HOME/.${NAME}rc; do
|
||||
if [ -f "$CONFIG" ] ; then
|
||||
if [ -f "$CONFIG" ] ; then
|
||||
readConfig "$CONFIG"
|
||||
fi
|
||||
done
|
||||
|
@ -187,7 +187,7 @@ JETTY_INSTALL_TRACE_FILE="start.jar"
|
|||
##################################################
|
||||
# Try to determine JETTY_HOME if not set
|
||||
##################################################
|
||||
if [ -z "$JETTY_HOME" ]
|
||||
if [ -z "$JETTY_HOME" ]
|
||||
then
|
||||
JETTY_SH=$0
|
||||
case "$JETTY_SH" in
|
||||
|
@ -200,7 +200,7 @@ then
|
|||
esac
|
||||
|
||||
if [ ! -f "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ]
|
||||
then
|
||||
then
|
||||
JETTY_HOME=
|
||||
fi
|
||||
fi
|
||||
|
@ -210,7 +210,7 @@ fi
|
|||
# No JETTY_HOME yet? We're out of luck!
|
||||
##################################################
|
||||
if [ -z "$JETTY_HOME" ]; then
|
||||
echo "** ERROR: JETTY_HOME not set, you need to set it or install in a standard location"
|
||||
echo "** ERROR: JETTY_HOME not set, you need to set it or install in a standard location"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -219,7 +219,7 @@ JETTY_HOME=$PWD
|
|||
|
||||
|
||||
##################################################
|
||||
# Set JETTY_BASE
|
||||
# Set JETTY_BASE
|
||||
##################################################
|
||||
if [ -z "$JETTY_BASE" ]; then
|
||||
JETTY_BASE=$JETTY_HOME
|
||||
|
@ -232,7 +232,7 @@ JETTY_BASE=$PWD
|
|||
#####################################################
|
||||
# Check that jetty is where we think it is
|
||||
#####################################################
|
||||
if [ ! -r "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ]
|
||||
if [ ! -r "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ]
|
||||
then
|
||||
echo "** ERROR: Oops! Jetty doesn't appear to be installed in $JETTY_HOME"
|
||||
echo "** ERROR: $JETTY_HOME/$JETTY_INSTALL_TRACE_FILE is not readable!"
|
||||
|
@ -244,7 +244,7 @@ fi
|
|||
# but only if no configurations were given on the
|
||||
# command line.
|
||||
##################################################
|
||||
if [ -z "$JETTY_CONF" ]
|
||||
if [ -z "$JETTY_CONF" ]
|
||||
then
|
||||
if [ -f $ETC/${NAME}.conf ]
|
||||
then
|
||||
|
@ -261,7 +261,7 @@ fi
|
|||
#####################################################
|
||||
# Find a location for the pid file
|
||||
#####################################################
|
||||
if [ -z "$JETTY_RUN" ]
|
||||
if [ -z "$JETTY_RUN" ]
|
||||
then
|
||||
JETTY_RUN=$(findDirectory -w /var/run /usr/var/run $JETTY_BASE /tmp)
|
||||
fi
|
||||
|
@ -269,12 +269,12 @@ fi
|
|||
#####################################################
|
||||
# Find a pid and state file
|
||||
#####################################################
|
||||
if [ -z "$JETTY_PID" ]
|
||||
if [ -z "$JETTY_PID" ]
|
||||
then
|
||||
JETTY_PID="$JETTY_RUN/${NAME}.pid"
|
||||
fi
|
||||
|
||||
if [ -z "$JETTY_STATE" ]
|
||||
if [ -z "$JETTY_STATE" ]
|
||||
then
|
||||
JETTY_STATE=$JETTY_BASE/${NAME}.state
|
||||
fi
|
||||
|
@ -289,7 +289,7 @@ JETTY_ARGS=(${JETTY_ARGS[*]} "jetty.state=$JETTY_STATE")
|
|||
##################################################
|
||||
# Get the list of config.xml files from jetty.conf
|
||||
##################################################
|
||||
if [ -f "$JETTY_CONF" ] && [ -r "$JETTY_CONF" ]
|
||||
if [ -f "$JETTY_CONF" ] && [ -r "$JETTY_CONF" ]
|
||||
then
|
||||
while read -r CONF
|
||||
do
|
||||
|
@ -297,18 +297,18 @@ then
|
|||
continue
|
||||
fi
|
||||
|
||||
if [ -d "$CONF" ]
|
||||
if [ -d "$CONF" ]
|
||||
then
|
||||
# assume it's a directory with configure.xml files
|
||||
# for example: /etc/jetty.d/
|
||||
# sort the files before adding them to the list of JETTY_ARGS
|
||||
for XMLFILE in "$CONF/"*.xml
|
||||
do
|
||||
if [ -r "$XMLFILE" ] && [ -f "$XMLFILE" ]
|
||||
if [ -r "$XMLFILE" ] && [ -f "$XMLFILE" ]
|
||||
then
|
||||
JETTY_ARGS=(${JETTY_ARGS[*]} "$XMLFILE")
|
||||
else
|
||||
echo "** WARNING: Cannot read '$XMLFILE' specified in '$JETTY_CONF'"
|
||||
echo "** WARNING: Cannot read '$XMLFILE' specified in '$JETTY_CONF'"
|
||||
fi
|
||||
done
|
||||
else
|
||||
|
@ -335,11 +335,11 @@ fi
|
|||
#####################################################
|
||||
# See if JETTY_LOGS is defined
|
||||
#####################################################
|
||||
if [ -z "$JETTY_LOGS" ] && [ -d $JETTY_BASE/logs ]
|
||||
if [ -z "$JETTY_LOGS" ] && [ -d $JETTY_BASE/logs ]
|
||||
then
|
||||
JETTY_LOGS=$JETTY_BASE/logs
|
||||
fi
|
||||
if [ -z "$JETTY_LOGS" ] && [ -d $JETTY_HOME/logs ]
|
||||
if [ -z "$JETTY_LOGS" ] && [ -d $JETTY_HOME/logs ]
|
||||
then
|
||||
JETTY_LOGS=$JETTY_HOME/logs
|
||||
fi
|
||||
|
@ -367,7 +367,7 @@ esac
|
|||
#####################################################
|
||||
|
||||
case "`uname`" in
|
||||
CYGWIN*)
|
||||
CYGWIN*)
|
||||
JETTY_HOME="`cygpath -w $JETTY_HOME`"
|
||||
JETTY_BASE="`cygpath -w $JETTY_BASE`"
|
||||
TMPDIR="`cygpath -w $TMPDIR`"
|
||||
|
@ -397,7 +397,7 @@ RUN_ARGS=(${JAVA_OPTIONS[@]} -jar "$JETTY_START" ${JETTY_ARGS[*]})
|
|||
RUN_CMD=("$JAVA" ${RUN_ARGS[@]})
|
||||
|
||||
#####################################################
|
||||
# Comment these out after you're happy with what
|
||||
# Comment these out after you're happy with what
|
||||
# the script is doing.
|
||||
#####################################################
|
||||
if (( DEBUG ))
|
||||
|
@ -422,12 +422,12 @@ case "$ACTION" in
|
|||
start)
|
||||
echo -n "Starting Jetty: "
|
||||
|
||||
if (( NO_START )); then
|
||||
if (( NO_START )); then
|
||||
echo "Not starting ${NAME} - NO_START=1";
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1
|
||||
if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1
|
||||
then
|
||||
unset CH_USER
|
||||
if [ -n "$JETTY_USER" ]
|
||||
|
@ -487,7 +487,7 @@ case "$ACTION" in
|
|||
echo -n "Stopping Jetty: "
|
||||
if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1; then
|
||||
start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s HUP
|
||||
|
||||
|
||||
TIMEOUT=30
|
||||
while running "$JETTY_PID"; do
|
||||
if (( TIMEOUT-- == 0 )); then
|
||||
|
@ -508,7 +508,7 @@ case "$ACTION" in
|
|||
exit 1
|
||||
fi
|
||||
kill "$PID" 2>/dev/null
|
||||
|
||||
|
||||
TIMEOUT=30
|
||||
while running $JETTY_PID; do
|
||||
if (( TIMEOUT-- == 0 )); then
|
||||
|
@ -563,7 +563,13 @@ case "$ACTION" in
|
|||
;;
|
||||
|
||||
check|status)
|
||||
echo "Checking arguments to Jetty: "
|
||||
if running "$JETTY_PID"
|
||||
then
|
||||
echo "Jetty running pid=$(< "$JETTY_PID")"
|
||||
else
|
||||
echo "Jetty NOT running"
|
||||
fi
|
||||
echo
|
||||
echo "START_INI = $START_INI"
|
||||
echo "START_D = $START_D"
|
||||
echo "JETTY_HOME = $JETTY_HOME"
|
||||
|
@ -579,10 +585,9 @@ case "$ACTION" in
|
|||
echo "JETTY_ARGS = ${JETTY_ARGS[*]}"
|
||||
echo "RUN_CMD = ${RUN_CMD[*]}"
|
||||
echo
|
||||
|
||||
|
||||
if running "$JETTY_PID"
|
||||
then
|
||||
echo "Jetty running pid=$(< "$JETTY_PID")"
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
|
|
@ -193,11 +193,12 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
|
|||
@Override
|
||||
public boolean onIdleExpired()
|
||||
{
|
||||
boolean close = delegate.onIdleTimeout();
|
||||
long idleTimeout = getEndPoint().getIdleTimeout();
|
||||
boolean close = delegate.onIdleTimeout(idleTimeout);
|
||||
if (multiplexed)
|
||||
close &= isFillInterested();
|
||||
if (close)
|
||||
close(new TimeoutException("Idle timeout " + getEndPoint().getIdleTimeout() + "ms"));
|
||||
close(new TimeoutException("Idle timeout " + idleTimeout + "ms"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,10 +74,13 @@ import static org.eclipse.jetty.http.HttpTokens.TAB;
|
|||
* is used to help the parsing of subsequent messages.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the system property "org.eclipse.jetty.http.HttpParser.STRICT" is set to true,
|
||||
* then the parser will strictly pass on the exact strings received for methods and header
|
||||
* fields. Otherwise a fast case insensitive string lookup is used that may alter the
|
||||
* case of the method and/or headers
|
||||
* The parser can work in varying compliance modes:
|
||||
* <dl>
|
||||
* <dt>RFC7230</dt><dd>(default) Compliance with RFC7230</dd>
|
||||
* <dt>RFC2616</dt><dd>Wrapped headers supported</dd>
|
||||
* <dt>STRICT</dt><dd>(misnomer) Adherence to Servlet Specification requirement for
|
||||
* exact case of header names, bypassing the header caches, which are case insensitive,
|
||||
* otherwise equivalent to RFC2616</dd>
|
||||
* </p>
|
||||
* <p>
|
||||
* @see <a href="http://tools.ietf.org/html/rfc7230">RFC 7230</a>
|
||||
|
@ -85,7 +88,8 @@ import static org.eclipse.jetty.http.HttpTokens.TAB;
|
|||
public class HttpParser
|
||||
{
|
||||
public static final Logger LOG = Log.getLogger(HttpParser.class);
|
||||
public final static boolean __STRICT=Boolean.getBoolean("org.eclipse.jetty.http.HttpParser.STRICT");
|
||||
@Deprecated
|
||||
public final static String __STRICT="org.eclipse.jetty.http.HttpParser.STRICT";
|
||||
public final static int INITIAL_URI_LENGTH=256;
|
||||
|
||||
/**
|
||||
|
@ -102,6 +106,9 @@ public class HttpParser
|
|||
*/
|
||||
public final static Trie<HttpField> CACHE = new ArrayTrie<>(2048);
|
||||
|
||||
// Compliance
|
||||
public enum Compliance { STRICT, RFC2616, RFC7230 };
|
||||
|
||||
// States
|
||||
public enum State
|
||||
{
|
||||
|
@ -139,7 +146,7 @@ public class HttpParser
|
|||
private final RequestHandler _requestHandler;
|
||||
private final ResponseHandler _responseHandler;
|
||||
private final int _maxHeaderBytes;
|
||||
private final boolean _strict;
|
||||
private final Compliance _compliance;
|
||||
private HttpField _field;
|
||||
private HttpHeader _header;
|
||||
private String _headerString;
|
||||
|
@ -218,49 +225,69 @@ public class HttpParser
|
|||
CACHE.put(new HttpField(HttpHeader.AUTHORIZATION,(String)null));
|
||||
CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null));
|
||||
}
|
||||
|
||||
private static Compliance compliance()
|
||||
{
|
||||
Boolean strict = Boolean.getBoolean(__STRICT);
|
||||
return strict?Compliance.STRICT:Compliance.RFC7230;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpParser(RequestHandler handler)
|
||||
{
|
||||
this(handler,-1,__STRICT);
|
||||
this(handler,-1,compliance());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpParser(ResponseHandler handler)
|
||||
{
|
||||
this(handler,-1,__STRICT);
|
||||
this(handler,-1,compliance());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpParser(RequestHandler handler,int maxHeaderBytes)
|
||||
{
|
||||
this(handler,maxHeaderBytes,__STRICT);
|
||||
this(handler,maxHeaderBytes,compliance());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpParser(ResponseHandler handler,int maxHeaderBytes)
|
||||
{
|
||||
this(handler,maxHeaderBytes,__STRICT);
|
||||
this(handler,maxHeaderBytes,compliance());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
@Deprecated
|
||||
public HttpParser(RequestHandler handler,int maxHeaderBytes,boolean strict)
|
||||
{
|
||||
this(handler,maxHeaderBytes,strict?Compliance.STRICT:compliance());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
@Deprecated
|
||||
public HttpParser(ResponseHandler handler,int maxHeaderBytes,boolean strict)
|
||||
{
|
||||
this(handler,maxHeaderBytes,strict?Compliance.STRICT:compliance());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpParser(RequestHandler handler,int maxHeaderBytes,Compliance compliance)
|
||||
{
|
||||
_handler=handler;
|
||||
_requestHandler=handler;
|
||||
_responseHandler=null;
|
||||
_maxHeaderBytes=maxHeaderBytes;
|
||||
_strict=strict;
|
||||
_compliance=compliance==null?compliance():compliance;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpParser(ResponseHandler handler,int maxHeaderBytes,boolean strict)
|
||||
public HttpParser(ResponseHandler handler,int maxHeaderBytes,Compliance compliance)
|
||||
{
|
||||
_handler=handler;
|
||||
_requestHandler=null;
|
||||
_responseHandler=handler;
|
||||
_maxHeaderBytes=maxHeaderBytes;
|
||||
_strict=strict;
|
||||
_compliance=compliance==null?compliance():compliance;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -556,7 +583,7 @@ public class HttpParser
|
|||
_length=_string.length();
|
||||
_methodString=takeString();
|
||||
HttpMethod method=HttpMethod.CACHE.get(_methodString);
|
||||
if (method!=null && !_strict)
|
||||
if (method!=null && _compliance!=Compliance.STRICT)
|
||||
_methodString=method.asString();
|
||||
setState(State.SPACE1);
|
||||
}
|
||||
|
@ -832,7 +859,7 @@ public class HttpParser
|
|||
_host=true;
|
||||
if (!(_field instanceof HostPortHttpField))
|
||||
{
|
||||
_field=new HostPortHttpField(_header,_strict?_headerString:_header.asString(),_valueString);
|
||||
_field=new HostPortHttpField(_header,_compliance==Compliance.STRICT?_headerString:_header.asString(),_valueString);
|
||||
add_to_connection_trie=_connectionFields!=null;
|
||||
}
|
||||
break;
|
||||
|
@ -861,7 +888,7 @@ public class HttpParser
|
|||
if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null)
|
||||
{
|
||||
if (_field==null)
|
||||
_field=new HttpField(_header,_strict?_headerString:_header.asString(),_valueString);
|
||||
_field=new HttpField(_header,_compliance==Compliance.STRICT?_headerString:_header.asString(),_valueString);
|
||||
_connectionFields.put(_field);
|
||||
}
|
||||
}
|
||||
|
@ -905,10 +932,32 @@ public class HttpParser
|
|||
case HttpTokens.COLON:
|
||||
case HttpTokens.SPACE:
|
||||
case HttpTokens.TAB:
|
||||
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Continuation");
|
||||
{
|
||||
if (_compliance.ordinal()>=Compliance.RFC7230.ordinal())
|
||||
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Continuation");
|
||||
|
||||
// header value without name - continuation?
|
||||
if (_valueString==null)
|
||||
{
|
||||
_string.setLength(0);
|
||||
_length=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
setString(_valueString);
|
||||
_string.append(' ');
|
||||
_length++;
|
||||
_valueString=null;
|
||||
}
|
||||
setState(State.HEADER_VALUE);
|
||||
break;
|
||||
}
|
||||
|
||||
case HttpTokens.LINE_FEED:
|
||||
{
|
||||
// process previous header
|
||||
parsedHeader();
|
||||
|
||||
_contentPosition=0;
|
||||
|
||||
// End of headers!
|
||||
|
@ -967,9 +1016,13 @@ public class HttpParser
|
|||
default:
|
||||
{
|
||||
// now handle the ch
|
||||
if (ch<=HttpTokens.SPACE)
|
||||
if (ch<HttpTokens.SPACE)
|
||||
throw new BadMessageException();
|
||||
|
||||
// process previous header
|
||||
parsedHeader();
|
||||
|
||||
// handle new header
|
||||
if (buffer.hasRemaining())
|
||||
{
|
||||
// Try a look ahead for the known header name and value.
|
||||
|
@ -982,7 +1035,7 @@ public class HttpParser
|
|||
final String n;
|
||||
final String v;
|
||||
|
||||
if (_strict)
|
||||
if (_compliance==Compliance.STRICT)
|
||||
{
|
||||
// Have to get the fields exactly from the buffer to match case
|
||||
String fn=field.getName();
|
||||
|
@ -1106,7 +1159,6 @@ public class HttpParser
|
|||
_valueString=null;
|
||||
_length=-1;
|
||||
|
||||
parsedHeader();
|
||||
setState(State.HEADER);
|
||||
break;
|
||||
}
|
||||
|
@ -1135,7 +1187,6 @@ public class HttpParser
|
|||
_valueString=takeString();
|
||||
_length=-1;
|
||||
}
|
||||
parsedHeader();
|
||||
setState(State.HEADER);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -218,6 +218,28 @@ public class HttpParserTest
|
|||
assertEquals("close", _val[1]);
|
||||
assertEquals(1, _headers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2616Continuations() throws Exception
|
||||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer(
|
||||
"GET / HTTP/1.0\015\012" +
|
||||
"Host: localhost\015\012" +
|
||||
"Name: value\015\012" +
|
||||
" extra\015\012" +
|
||||
"\015\012");
|
||||
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser= new HttpParser(handler,4096,HttpParser.Compliance.RFC2616);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
Assert.assertThat(_bad,Matchers.nullValue());
|
||||
assertEquals("Host", _hdr[0]);
|
||||
assertEquals("localhost", _val[0]);
|
||||
assertEquals("Name", _hdr[1]);
|
||||
assertEquals("value extra", _val[1]);
|
||||
assertEquals(1, _headers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test7230NoContinuations() throws Exception
|
||||
|
@ -230,13 +252,12 @@ public class HttpParserTest
|
|||
"\015\012");
|
||||
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser= new HttpParser(handler);
|
||||
HttpParser parser= new HttpParser(handler,4096,HttpParser.Compliance.RFC7230);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
Assert.assertThat(_bad,Matchers.notNullValue());
|
||||
Assert.assertThat(_bad,Matchers.containsString("Bad Continuation"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test7230NoWhiteSpaceInName() throws Exception
|
||||
|
@ -581,9 +602,9 @@ public class HttpParserTest
|
|||
"cOnNeCtIoN: ClOsE\015\012"+
|
||||
"\015\012");
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser= new HttpParser(handler,-1,false);
|
||||
HttpParser parser= new HttpParser(handler,-1,HttpParser.Compliance.RFC7230);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
assertNull(_bad);
|
||||
assertEquals("GET", _methodOrVersion);
|
||||
assertEquals("/", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
|
@ -603,9 +624,9 @@ public class HttpParserTest
|
|||
"cOnNeCtIoN: ClOsE\015\012"+
|
||||
"\015\012");
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser= new HttpParser(handler,-1,true);
|
||||
HttpParser parser= new HttpParser(handler,-1,HttpParser.Compliance.STRICT);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
assertNull(_bad);
|
||||
assertEquals("gEt", _methodOrVersion);
|
||||
assertEquals("/", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
|
@ -1562,26 +1583,6 @@ public class HttpParserTest
|
|||
assertTrue(field==_fields.get(0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFolded() throws Exception
|
||||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer(
|
||||
"GET / HTTP/1.0\015\012" +
|
||||
"Host: localhost\015\012" +
|
||||
"Connection: close\015\012" +
|
||||
"Content-Type: application/soap+xml; charset=utf-8; \015\012"+
|
||||
"\taction=\"xxx\" \015\012" +
|
||||
"\015\012");
|
||||
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser= new HttpParser(handler);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
assertFalse(_headerCompleted);
|
||||
assertEquals(_bad, "Bad Continuation");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParseRequest() throws Exception
|
||||
|
|
|
@ -615,7 +615,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
|
|||
private void frame(HTTP2Flusher.Entry entry, boolean flush)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Sending {}", entry.frame);
|
||||
LOG.debug("{} {}", flush ? "Sending" : "Queueing", entry.frame);
|
||||
// Ping frames are prepended to process them as soon as possible.
|
||||
boolean queued = entry.frame.getType() == FrameType.PING ? flusher.prepend(entry) : flusher.append(entry);
|
||||
if (queued && flush)
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.jetty.client.HttpDestination;
|
|||
import org.eclipse.jetty.client.Origin;
|
||||
import org.eclipse.jetty.client.api.Connection;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http2.HTTP2Session;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.client.HTTP2Client;
|
||||
import org.eclipse.jetty.http2.client.HTTP2ClientConnectionFactory;
|
||||
|
@ -187,7 +188,7 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements
|
|||
@Override
|
||||
public boolean onIdleTimeout(Session session)
|
||||
{
|
||||
return connection.onIdleTimeout();
|
||||
return connection.onIdleTimeout(((HTTP2Session)session).getEndPoint().getIdleTimeout());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -294,7 +294,7 @@ public class HTTP2CServerTest extends AbstractServerTest
|
|||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
HttpConnection connection = new HttpConnection(getHttpConfiguration(), connector, endPoint)
|
||||
HttpConnection connection = new HttpConnection(getHttpConfiguration(), connector, endPoint,getHttpCompliance())
|
||||
{
|
||||
@Override
|
||||
public void onFillable()
|
||||
|
|
|
@ -371,7 +371,7 @@ public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
|||
protected void onIdleExpired(TimeoutException timeout)
|
||||
{
|
||||
Connection connection = _connection;
|
||||
if (connection != null && !_connection.onIdleExpired())
|
||||
if (connection != null && !connection.onIdleExpired())
|
||||
return;
|
||||
|
||||
boolean output_shutdown=isOutputShutdown();
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
|||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.Locker;
|
||||
|
||||
/**
|
||||
* Container class for the MBean instances
|
||||
|
@ -51,6 +52,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
__unique.clear();
|
||||
}
|
||||
|
||||
private final Locker _lock = new Locker();
|
||||
private final MBeanServer _mbeanServer;
|
||||
private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
|
||||
private String _domain = null;
|
||||
|
@ -63,8 +65,11 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
*/
|
||||
public synchronized ObjectName findMBean(Object object)
|
||||
{
|
||||
ObjectName bean = _beans.get(object);
|
||||
return bean == null ? null : bean;
|
||||
try (Locker.Lock lock = _lock.lock())
|
||||
{
|
||||
ObjectName bean = _beans.get(object);
|
||||
return bean == null ? null : bean;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,11 +80,14 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
*/
|
||||
public synchronized Object findBean(ObjectName oname)
|
||||
{
|
||||
for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
|
||||
try (Locker.Lock lock = _lock.lock())
|
||||
{
|
||||
ObjectName bean = entry.getValue();
|
||||
if (bean.equals(oname))
|
||||
return entry.getKey();
|
||||
for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
|
||||
{
|
||||
ObjectName bean = entry.getValue();
|
||||
if (bean.equals(oname))
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -130,32 +138,31 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("beanAdded {}->{}",parent,obj);
|
||||
|
||||
// Is their an object name for the parent
|
||||
ObjectName pname=null;
|
||||
if (parent!=null)
|
||||
|
||||
try (Locker.Lock lock = _lock.lock())
|
||||
{
|
||||
pname=_beans.get(parent);
|
||||
if (pname==null)
|
||||
// Is their an object name for the parent
|
||||
ObjectName pname=null;
|
||||
if (parent!=null)
|
||||
{
|
||||
// create the parent bean
|
||||
beanAdded(null,parent);
|
||||
pname=_beans.get(parent);
|
||||
if (pname==null)
|
||||
{
|
||||
// create the parent bean
|
||||
beanAdded(null,parent);
|
||||
pname=_beans.get(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Does an mbean already exist?
|
||||
if (obj == null || _beans.containsKey(obj))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Does an mbean already exist?
|
||||
if (obj == null || _beans.containsKey(obj))
|
||||
return;
|
||||
|
||||
// Create an MBean for the object
|
||||
Object mbean = ObjectMBean.mbeanFor(obj);
|
||||
if (mbean == null)
|
||||
return;
|
||||
|
||||
|
||||
ObjectName oname = null;
|
||||
if (mbean instanceof ObjectMBean)
|
||||
{
|
||||
|
@ -171,7 +178,6 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
if (domain == null)
|
||||
domain = obj.getClass().getPackage().getName();
|
||||
|
||||
|
||||
String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
|
||||
int dot = type.lastIndexOf('.');
|
||||
if (dot >= 0)
|
||||
|
@ -183,10 +189,10 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
String context = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectContextBasis()):null;
|
||||
if (context==null && pname!=null)
|
||||
context=pname.getKeyProperty("context");
|
||||
|
||||
|
||||
if (context != null && context.length()>1)
|
||||
buf.append("context=").append(context).append(",");
|
||||
|
||||
|
||||
buf.append("type=").append(type);
|
||||
|
||||
String name = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectNameBasis()):context;
|
||||
|
@ -194,7 +200,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
buf.append(",").append("name=").append(name);
|
||||
|
||||
String basis = buf.toString();
|
||||
|
||||
|
||||
AtomicInteger count = __unique.get(basis);
|
||||
if (count==null)
|
||||
{
|
||||
|
@ -202,7 +208,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
if (count==null)
|
||||
count=__unique.get(basis);
|
||||
}
|
||||
|
||||
|
||||
oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count.getAndIncrement());
|
||||
}
|
||||
|
||||
|
@ -210,7 +216,6 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Registered {}", oinstance.getObjectName());
|
||||
_beans.put(obj, oinstance.getObjectName());
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -223,23 +228,26 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("beanRemoved {}",obj);
|
||||
ObjectName bean = _beans.remove(obj);
|
||||
|
||||
if (bean != null)
|
||||
try (Locker.Lock lock = _lock.lock())
|
||||
{
|
||||
try
|
||||
ObjectName bean = _beans.remove(obj);
|
||||
|
||||
if (bean != null)
|
||||
{
|
||||
_mbeanServer.unregisterMBean(bean);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unregistered {}", bean);
|
||||
}
|
||||
catch (javax.management.InstanceNotFoundException e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
try
|
||||
{
|
||||
_mbeanServer.unregisterMBean(bean);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unregistered {}", bean);
|
||||
}
|
||||
catch (javax.management.InstanceNotFoundException e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,8 +266,11 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
@Override
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
ContainerLifeCycle.dumpObject(out,this);
|
||||
ContainerLifeCycle.dump(out, indent, _beans.entrySet());
|
||||
try (Locker.Lock lock = _lock.lock())
|
||||
{
|
||||
ContainerLifeCycle.dumpObject(out,this);
|
||||
ContainerLifeCycle.dump(out, indent, _beans.entrySet());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -270,17 +281,22 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
|
||||
public void destroy()
|
||||
{
|
||||
for (ObjectName oname : _beans.values())
|
||||
if (oname!=null)
|
||||
try (Locker.Lock lock = _lock.lock())
|
||||
{
|
||||
for (ObjectName oname : _beans.values())
|
||||
{
|
||||
try
|
||||
if (oname!=null)
|
||||
{
|
||||
_mbeanServer.unregisterMBean(oname);
|
||||
}
|
||||
catch (MBeanRegistrationException | InstanceNotFoundException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
try
|
||||
{
|
||||
_mbeanServer.unregisterMBean(oname);
|
||||
}
|
||||
catch (MBeanRegistrationException | InstanceNotFoundException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
* @return true if logging is enabled
|
||||
*/
|
||||
protected abstract boolean isEnabled();
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
|
@ -82,7 +82,7 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
public abstract void write(String requestEntry) throws IOException;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
|
||||
private void append(StringBuilder buf,String s)
|
||||
{
|
||||
if (s==null || s.length()==0)
|
||||
|
@ -90,7 +90,7 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
else
|
||||
buf.append(s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes the request and response information to the output stream.
|
||||
*
|
||||
|
@ -101,9 +101,6 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
{
|
||||
try
|
||||
{
|
||||
int status = response.getCommittedMetaData().getStatus();
|
||||
long written = response.getHttpChannel().getBytesWritten();
|
||||
|
||||
if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
|
||||
return;
|
||||
|
||||
|
@ -147,6 +144,7 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
append(buf,request.getProtocol());
|
||||
buf.append("\" ");
|
||||
|
||||
int status = response.getCommittedMetaData().getStatus();
|
||||
if (status >=0)
|
||||
{
|
||||
buf.append((char)('0' + ((status / 100) % 10)));
|
||||
|
@ -156,6 +154,7 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
else
|
||||
buf.append(status);
|
||||
|
||||
long written = response.getHttpChannel().getBytesWritten();
|
||||
if (written >= 0)
|
||||
{
|
||||
buf.append(' ');
|
||||
|
@ -180,7 +179,7 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
|
||||
|
||||
if (_extended)
|
||||
logExtended(request, buf);
|
||||
logExtended(buf, request, response);
|
||||
|
||||
if (_logCookies)
|
||||
{
|
||||
|
@ -221,18 +220,12 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* Writes extended request and response information to the output stream.
|
||||
*
|
||||
* @param request request object
|
||||
* @param b StringBuilder to write to
|
||||
* @throws IOException if unable to log the extended information
|
||||
* @deprecated override {@link #logExtended(StringBuilder, Request, Response)} instead
|
||||
*/
|
||||
protected void logExtended(Request request,
|
||||
StringBuilder b) throws IOException
|
||||
@Deprecated
|
||||
protected void logExtended(Request request, StringBuilder b) throws IOException
|
||||
{
|
||||
String referer = request.getHeader(HttpHeader.REFERER.toString());
|
||||
if (referer == null)
|
||||
|
@ -255,6 +248,18 @@ public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implement
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes extended request and response information to the output stream.
|
||||
*
|
||||
* @param b StringBuilder to write to
|
||||
* @param request request object
|
||||
* @param response response object
|
||||
* @throws IOException if unable to log the extended information
|
||||
*/
|
||||
protected void logExtended(StringBuilder b, Request request, Response response) throws IOException
|
||||
{
|
||||
logExtended(request, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set request paths that will not be logged.
|
||||
|
|
|
@ -90,7 +90,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
return last;
|
||||
}
|
||||
|
||||
public HttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint)
|
||||
public HttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint, HttpParser.Compliance compliance)
|
||||
{
|
||||
super(endPoint, connector.getExecutor());
|
||||
_config = config;
|
||||
|
@ -99,7 +99,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
_generator = newHttpGenerator();
|
||||
_channel = newHttpChannel();
|
||||
_input = _channel.getRequest().getHttpInput();
|
||||
_parser = newHttpParser();
|
||||
_parser = newHttpParser(compliance);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("New HTTP Connection {}", this);
|
||||
}
|
||||
|
@ -119,9 +119,9 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
return new HttpChannelOverHttp(this, _connector, _config, getEndPoint(), this);
|
||||
}
|
||||
|
||||
protected HttpParser newHttpParser()
|
||||
protected HttpParser newHttpParser(HttpParser.Compliance compliance)
|
||||
{
|
||||
return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize());
|
||||
return new HttpParser(newRequestHandler(), getHttpConfiguration().getRequestHeaderSize(), compliance);
|
||||
}
|
||||
|
||||
protected HttpParser.RequestHandler newRequestHandler()
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
@ -31,6 +32,7 @@ import org.eclipse.jetty.util.annotation.Name;
|
|||
public class HttpConnectionFactory extends AbstractConnectionFactory implements HttpConfiguration.ConnectionFactory
|
||||
{
|
||||
private final HttpConfiguration _config;
|
||||
private HttpParser.Compliance _httpCompliance=HttpParser.Compliance.RFC7230;
|
||||
|
||||
public HttpConnectionFactory()
|
||||
{
|
||||
|
@ -52,9 +54,24 @@ public class HttpConnectionFactory extends AbstractConnectionFactory implements
|
|||
return _config;
|
||||
}
|
||||
|
||||
public HttpParser.Compliance getHttpCompliance()
|
||||
{
|
||||
return _httpCompliance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param httpCompliance String value of {@link HttpParser.Compliance}
|
||||
*/
|
||||
public void setHttpCompliance(HttpParser.Compliance httpCompliance)
|
||||
{
|
||||
_httpCompliance = httpCompliance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
return configure(new HttpConnection(_config, connector, endPoint), connector, endPoint);
|
||||
return configure(new HttpConnection(_config, connector, endPoint, _httpCompliance), connector, endPoint);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.ChannelEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
@ -55,7 +56,7 @@ public class ExtendedServerTest extends HttpServerTestBase
|
|||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
return configure(new ExtendedHttpConnection(getHttpConfiguration(), connector, endPoint), connector, endPoint);
|
||||
return configure(new ExtendedHttpConnection(getHttpConfiguration(), connector, endPoint,getHttpCompliance()), connector, endPoint);
|
||||
}
|
||||
})
|
||||
{
|
||||
|
@ -93,9 +94,9 @@ public class ExtendedServerTest extends HttpServerTestBase
|
|||
|
||||
private static class ExtendedHttpConnection extends HttpConnection
|
||||
{
|
||||
public ExtendedHttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint)
|
||||
public ExtendedHttpConnection(HttpConfiguration config, Connector connector, EndPoint endPoint, HttpParser.Compliance compliance)
|
||||
{
|
||||
super(config,connector,endPoint);
|
||||
super(config,connector,endPoint,compliance);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,7 +54,7 @@ public class SlowClientWithPipelinedRequestTest
|
|||
@Override
|
||||
public Connection newConnection(Connector connector, EndPoint endPoint)
|
||||
{
|
||||
return configure(new HttpConnection(new HttpConfiguration(),connector,endPoint)
|
||||
return configure(new HttpConnection(getHttpConfiguration(),connector,endPoint,getHttpCompliance())
|
||||
{
|
||||
@Override
|
||||
public void onFillable()
|
||||
|
|
Loading…
Reference in New Issue