Merge branch 'jetty-9.4.x' into jetty-9.4.x-3989-selector-failure

This commit is contained in:
Joakim Erdfelt 2019-09-06 14:35:17 -05:00
commit 0596d6c352
117 changed files with 969 additions and 291 deletions

View File

@ -173,7 +173,7 @@ public class TestSecurityAnnotationConversions
public void testMethodAnnotation() throws Exception
{
//ServletSecurity annotation with HttpConstraint of TransportGuarantee.CONFIDENTIAL, and a list of rolesAllowed, and
//a HttpMethodConstraint for GET method that permits all and has TransportGuarantee.NONE (ie is default)
//an HttpMethodConstraint for GET method that permits all and has TransportGuarantee.NONE (ie is default)
WebAppContext wac = makeWebAppContext(Method1Servlet.class.getCanonicalName(), "method1Servlet", new String[]{
"/foo/*", "*.foo"

View File

@ -28,7 +28,7 @@ import org.eclipse.jetty.io.ClientConnectionFactory;
* in order to plug-in a different transport for {@link HttpClient}.
* <p>
* While the {@link HttpClient} APIs define the HTTP semantic (request, response, headers, etc.)
* <em>how</em> a HTTP exchange is carried over the network depends on implementations of this class.
* <em>how</em> an HTTP exchange is carried over the network depends on implementations of this class.
* <p>
* The default implementation uses the HTTP protocol to carry over the network the HTTP exchange,
* but the HTTP exchange may also be carried using the FCGI protocol, the HTTP/2 protocol or,

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.util.log.Logger;
/**
* {@link HttpContent} is a stateful, linear representation of the request content provided
* by a {@link ContentProvider} that can be traversed one-way to obtain content buffers to
* send to a HTTP server.
* send to an HTTP server.
* <p>
* {@link HttpContent} offers the notion of a one-way cursor to traverse the content.
* The cursor starts in a virtual "before" position and can be advanced using {@link #advance()}

View File

@ -51,7 +51,7 @@ import org.eclipse.jetty.util.log.Logger;
* <ol>
* <li>{@link #responseBegin(HttpExchange)}, when the HTTP response data containing the HTTP status code
* is available</li>
* <li>{@link #responseHeader(HttpExchange, HttpField)}, when a HTTP field is available</li>
* <li>{@link #responseHeader(HttpExchange, HttpField)}, when an HTTP field is available</li>
* <li>{@link #responseHeaders(HttpExchange)}, when all HTTP headers are available</li>
* <li>{@link #responseContent(HttpExchange, ByteBuffer, Callback)}, when HTTP content is available</li>
* <li>{@link #responseSuccess(HttpExchange)}, when the response is successful</li>

View File

@ -82,7 +82,7 @@ public class HttpRedirector
/**
* @param response the response to check for redirects
* @return whether the response code is a HTTP redirect code
* @return whether the response code is an HTTP redirect code
*/
public boolean isRedirect(Response response)
{

View File

@ -869,7 +869,7 @@ public class HttpRequest implements Request
}
catch (URISyntaxException x)
{
// The "path" of a HTTP request may not be a URI,
// The "path" of an HTTP request may not be a URI,
// for example for CONNECT 127.0.0.1:8080.
return null;
}

View File

@ -40,7 +40,7 @@ import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.util.Fields;
/**
* <p>{@link Request} represents a HTTP request, and offers a fluent interface to customize
* <p>{@link Request} represents an HTTP request, and offers a fluent interface to customize
* various attributes such as the path, the headers, the content, etc.</p>
* <p>You can create {@link Request} objects via {@link HttpClient#newRequest(String)} and
* you can send them using either {@link #send()} for a blocking semantic, or

View File

@ -29,7 +29,7 @@ import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.util.Callback;
/**
* <p>{@link Response} represents a HTTP response and offers methods to retrieve status code, HTTP version
* <p>{@link Response} represents an HTTP response and offers methods to retrieve status code, HTTP version
* and headers.</p>
* <p>{@link Response} objects are passed as parameters to {@link Response.Listener} callbacks, or as
* future result of {@link Request#send()}.</p>

View File

@ -161,7 +161,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
}
/**
* Parses a HTTP response in the receivers buffer.
* Parses an HTTP response in the receivers buffer.
*
* @return true to indicate that parsing should be interrupted (and will be resumed by another thread).
*/

View File

@ -100,7 +100,7 @@ public class HostnameVerificationTest
/**
* This test is supposed to verify that hostname verification works as described in:
* http://www.ietf.org/rfc/rfc2818.txt section 3.1. It uses a certificate with a common name different to localhost
* and sends a request to localhost. This should fail with a SSLHandshakeException.
* and sends a request to localhost. This should fail with an SSLHandshakeException.
*
* @throws Exception on test failure
*/

View File

@ -494,7 +494,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
.scheme(scenario.getScheme())
.onResponseBegin(response1 ->
{
// Simulate a HTTP 1.0 response has been received.
// Simulate an HTTP 1.0 response has been received.
((HttpResponse)response1).version(HttpVersion.HTTP_1_0);
})
.send();

View File

@ -1803,7 +1803,7 @@ public class SslBytesServerTest extends SslBytesTest
assertTrue(latch.await(idleTimeout * 2, TimeUnit.MILLISECONDS));
// Be sure that the server sent a SSL close alert
// Be sure that the server sent an SSL close alert
TLSRecord record = proxy.readFromServer();
assertNotNull(record);
assertEquals(TLSRecord.Type.ALERT, record.getType());

View File

@ -26,7 +26,7 @@ import javax.servlet.ServletResponseWrapper;
/**
* Continuation.
* <p>
* A continuation is a mechanism by which a HTTP Request can be suspended and
* A continuation is a mechanism by which an HTTP Request can be suspended and
* restarted after a timeout or an asynchronous event has occurred.
* <p>
* The continuation mechanism is a portable mechanism that will work

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -743,7 +743,7 @@ If you are using Conscrypt with Java 8, you must exclude `TLSv1.3` protocol as i
==== Configuring SNI
From Java 8, the JVM contains support for the http://en.wikipedia.org/wiki/Server_Name_Indication[Server Name Indicator (SNI)] extension, which allows a SSL connection handshake to indicate one or more DNS names that it applies to.
From Java 8, the JVM contains support for the http://en.wikipedia.org/wiki/Server_Name_Indication[Server Name Indicator (SNI)] extension, which allows an SSL connection handshake to indicate one or more DNS names that it applies to.
To support this, the `SslContextFactory` is used.
The `SslContextFactory` will look for multiple X509 certificates within the keystore, each of which may have multiple DNS names (including wildcards) associated with the http://en.wikipedia.org/wiki/SubjectAltName[Subject Alternate Name] extension.

View File

@ -32,11 +32,14 @@ _____
.Jetty Versions
[width="100%",cols="12%,9%,15%,6%,21%,10%,6%,21%",options="header",]
|=======================================================================
|Version |Year |Home |JVM |Protocols |Servlet |JSP |Status
|Version |Year |Home |Min JVM |Protocols |Servlet |JSP |Status
|10 |2019- |Eclipse |11 ^(1)^ |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |4.0.2 |2.3 |*UNSTABLE / Alpha*
|9.4 |2016- |Eclipse |1.8 |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|9.3 |2015- |Eclipse |1.8 |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|9.2 |2014-2018 |Eclipse |1.7 |HTTP/1.1 RFC2616, javax.websocket, SPDY v3 |3.1 |2.3 |Deprecated / *End of Life January 2018*
|8 |2009-2014 |Eclipse/Codehaus |1.6 |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |3.0 |2.2 |Deprecated / *End of Life November 2014*
|9.3 |2015- |Eclipse |1.8 ^(2)^ |HTTP/1.1 (RFC 7230), HTTP/2 (RFC 7540), WebSocket (RFC 6455, JSR 356), FastCGI |3.1 |2.3 |Stable
|9.2 |2014-2018 |Eclipse |1.7 ^(2)^ |HTTP/1.1 RFC2616, javax.websocket, SPDY v3 |3.1 |2.3 |Deprecated / *End of Life January 2018*
|9.1 |2013-2014 |Eclipse |1.7 ^(2)^ |HTTP/1.1 RFC2616 |3.1 |2.3 |Deprecated / *End of Life May 2014*
|9.0 |2013-2013 |Eclipse |1.7 ^(2)^ |HTTP/1.1 RFC2616 |3.1-beta |2.3 |Deprecated / *End of Life November 2013*
|8 |2009-2014 |Eclipse/Codehaus |1.6 ^(2)^ |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |3.0 |2.2 |Deprecated / *End of Life November 2014*
|7 |2008-2014 |Eclipse/Codehaus |1.5 |HTTP/1.1 RFC2616, WebSocket RFC 6455, SPDY v3 |2.5 |2.1 |Deprecated / *End of Life November 2014*
|6 |2006-2010 |Codehaus |1.4-1.5 |HTTP/1.1 RFC2616 |2.5 |2.0 |Deprecated / *End of Life November 2010*
|5 |2003-2009 |Sourceforge |1.2-1.5 |HTTP/1.1 RFC2616 |2.4 |2.0 |Antique
@ -45,3 +48,6 @@ _____
|2 |1998-2000 |Mortbay |1.1 |HTTP/1.0 RFC1945 |2.1 |1.0 |Legendary
|1 |1995-1998 |Mortbay |1.0 |HTTP/1.0 RFC1945 |- |- |Mythical
|=======================================================================
1. JPMS module support is optional
2. JDK9 and newer is not supported if using MultiRelease JAR Files, or Bytecode / Annotation scanning.

View File

@ -44,7 +44,7 @@ import org.eclipse.jetty.util.ProcessorUtils;
/**
* Specific implementation of {@link org.eclipse.jetty.proxy.AsyncProxyServlet.Transparent} for FastCGI.
* <p>
* This servlet accepts a HTTP request and transforms it into a FastCGI request
* This servlet accepts an HTTP request and transforms it into a FastCGI request
* that is sent to the FastCGI server specified in the {@code proxyTo}
* init-param.
* <p>

View File

@ -21,7 +21,7 @@ package org.eclipse.jetty.http;
import org.eclipse.jetty.util.HostPort;
/**
* A HttpField holding a preparsed Host and port number
* An HttpField holding a preparsed Host and port number
*
* @see HostPort
*/

View File

@ -23,7 +23,7 @@ import java.util.Objects;
import org.eclipse.jetty.util.StringUtil;
/**
* A HTTP Field
* An HTTP Field
*/
public class HttpField
{
@ -37,7 +37,10 @@ public class HttpField
public HttpField(HttpHeader header, String name, String value)
{
_header = header;
_name = name;
if (_header != null && name == null)
_name = _header.asString();
else
_name = Objects.requireNonNull(name);
_value = value;
}
@ -325,8 +328,6 @@ public class HttpField
return false;
if (!_name.equalsIgnoreCase(field.getName()))
return false;
if (_value == null && field.getValue() != null)
return false;
return Objects.equals(_value, field.getValue());
}

View File

@ -48,7 +48,7 @@ public enum HttpMethod
* @param bytes Array containing ISO-8859-1 characters
* @param position The first valid index
* @param limit The first non valid index
* @return A HttpMethod if a match or null if no easy match.
* @return An HttpMethod if a match or null if no easy match.
*/
public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
{
@ -110,7 +110,7 @@ public enum HttpMethod
* Optimized lookup to find a method name and trailing space in a byte array.
*
* @param buffer buffer containing ISO-8859-1 characters, it is not modified.
* @return A HttpMethod if a match or null if no easy match.
* @return An HttpMethod if a match or null if no easy match.
*/
public static HttpMethod lookAheadGet(ByteBuffer buffer)
{

View File

@ -477,7 +477,7 @@ public class HttpParser
return t;
}
/* Quick lookahead for the start state looking for a request method or a HTTP version,
/* Quick lookahead for the start state looking for a request method or an HTTP version,
* otherwise skip white space until something else to parse.
*/
private boolean quickStart(ByteBuffer buffer)
@ -1873,14 +1873,14 @@ public class HttpParser
boolean messageComplete();
/**
* This is the method called by parser when a HTTP Header name and value is found
* This is the method called by parser when an HTTP Header name and value is found
*
* @param field The field parsed
*/
void parsedHeader(HttpField field);
/**
* This is the method called by parser when a HTTP Trailer name and value is found
* This is the method called by parser when an HTTP Trailer name and value is found
*
* @param field The field parsed
*/
@ -1890,7 +1890,7 @@ public class HttpParser
/**
* Called to signal that an EOF was received unexpectedly
* during the parsing of a HTTP message
* during the parsing of an HTTP message
*/
void earlyEOF();

View File

@ -31,7 +31,7 @@ import org.eclipse.jetty.util.UrlEncoded;
/**
* Http URI.
* Parse a HTTP URI from a string or byte array. Given a URI
* Parse an HTTP URI from a string or byte array. Given a URI
* <code>http://user@host:port/path/info;param?query#fragment</code>
* this class will split it into the following undecoded optional elements:<ul>
* <li>{@link #getScheme()} - http:</li>

View File

@ -42,12 +42,12 @@ public enum HttpVersion
}
/**
* Optimised lookup to find a Http Version and whitespace in a byte array.
* Optimised lookup to find an Http Version and whitespace in a byte array.
*
* @param bytes Array containing ISO-8859-1 characters
* @param position The first valid index
* @param limit The first non valid index
* @return A HttpMethod if a match or null if no easy match.
* @return An HttpMethod if a match or null if no easy match.
*/
public static HttpVersion lookAheadGet(byte[] bytes, int position, int limit)
{
@ -84,10 +84,10 @@ public enum HttpVersion
}
/**
* Optimised lookup to find a HTTP Version and trailing white space in a byte array.
* Optimised lookup to find an HTTP Version and trailing white space in a byte array.
*
* @param buffer buffer containing ISO-8859-1 characters
* @return A HttpVersion if a match or null if no easy match.
* @return An HttpVersion if a match or null if no easy match.
*/
public static HttpVersion lookAheadGet(ByteBuffer buffer)
{

View File

@ -29,7 +29,7 @@ import org.eclipse.jetty.util.log.Logger;
/**
* Pre encoded HttpField.
* <p>A HttpField that will be cached and used many times can be created as
* <p>An HttpField that will be cached and used many times can be created as
* a {@link PreEncodedHttpField}, which will use the {@link HttpFieldPreEncoder}
* instances discovered by the {@link ServiceLoader} to pre-encode the header
* for each version of HTTP in use. This will save garbage

View File

@ -30,6 +30,8 @@ import java.util.NoSuchElementException;
import org.eclipse.jetty.util.BufferUtil;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@ -666,6 +668,41 @@ public class HttpFieldsTest
assertFalse(header.containsKey("n11"));
}
@ParameterizedTest
@ValueSource(strings = {"Host", "host", "HOST", "HoSt", "Connection", "CONNECTION", "connection", "CoNnEcTiOn"})
public void testContainsKeyTrue(String keyName)
{
HttpFields fields = new HttpFields();
fields.put("Host", "localhost");
HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus");
fields.put(namelessField);
assertTrue(fields.containsKey(keyName), "containsKey('" + keyName + "')");
}
@ParameterizedTest
@ValueSource(strings = {"Content-Type", "Content-Length", "X-Bogus", ""})
public void testContainsKeyFalse(String keyName)
{
HttpFields fields = new HttpFields();
fields.add("Host", "localhost");
HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus");
fields.put(namelessField);
assertFalse(fields.containsKey(keyName), "containsKey('" + keyName + "')");
}
@Test
public void testPreventNullField()
{
HttpFields fields = new HttpFields();
assertThrows(NullPointerException.class, () ->
{
HttpField nullNullField = new HttpField(null, null, "bogus");
fields.put(nullNullField);
});
}
@Test
public void testIteration() throws Exception
{

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* A HTTP Testing helper class.
* An HTTP Testing helper class.
*
* Example usage:
* <pre>

View File

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -46,6 +45,7 @@ import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.GoAwayFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.http2.parser.RateControl;
import org.eclipse.jetty.http2.parser.ServerParser;
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
import org.eclipse.jetty.server.Connector;
@ -152,7 +152,7 @@ public class HTTP2Test extends AbstractTest
start(new HttpServlet()
{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
resp.getOutputStream().write(content);
}
@ -200,7 +200,7 @@ public class HTTP2Test extends AbstractTest
start(new EmptyHttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException
{
IO.copy(request.getInputStream(), response.getOutputStream());
}
@ -244,7 +244,7 @@ public class HTTP2Test extends AbstractTest
start(new HttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException
{
int download = request.getIntHeader(downloadBytes);
byte[] content = new byte[download];
@ -287,7 +287,7 @@ public class HTTP2Test extends AbstractTest
start(new HttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
protected void service(HttpServletRequest request, HttpServletResponse response)
{
response.setStatus(status);
}
@ -322,7 +322,7 @@ public class HTTP2Test extends AbstractTest
start(new HttpServlet()
{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
protected void service(HttpServletRequest request, HttpServletResponse response)
{
assertEquals(host, request.getServerName());
assertEquals(port, request.getServerPort());
@ -747,7 +747,7 @@ public class HTTP2Test extends AbstractTest
RawHTTP2ServerConnectionFactory connectionFactory = new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), serverListener)
{
@Override
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener, RateControl rateControl)
{
return super.newServerParser(connector, new ServerParser.Listener.Wrapper(listener)
{
@ -757,7 +757,7 @@ public class HTTP2Test extends AbstractTest
super.onGoAway(frame);
goAwayLatch.countDown();
}
});
}, rateControl);
}
};
prepareServer(connectionFactory);

View File

@ -170,7 +170,7 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
// and here we keep track of its max value.
// Updating the max session recv window is done here
// so that if a peer decides to send an unilateral
// so that if a peer decides to send a unilateral
// window update to enlarge the session window,
// without the corresponding data consumption, here
// we can track it.

View File

@ -40,7 +40,7 @@ public enum ErrorCode
*/
INTERNAL_ERROR(2),
/**
* Indicates a HTTP/2 flow control violation.
* Indicates an HTTP/2 flow control violation.
*/
FLOW_CONTROL_ERROR(3),
/**
@ -68,7 +68,7 @@ public enum ErrorCode
*/
COMPRESSION_ERROR(9),
/**
* Indicates that the connection established by a HTTP CONNECT was abnormally closed.
* Indicates that the connection established by an HTTP CONNECT was abnormally closed.
*/
HTTP_CONNECT_ERROR(10),
/**

View File

@ -57,6 +57,7 @@ import org.eclipse.jetty.util.AtomicBiInteger;
import org.eclipse.jetty.util.Atomics;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.CountingCallback;
import org.eclipse.jetty.util.MathUtils;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.Retainable;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -460,47 +461,33 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
int windowDelta = frame.getWindowDelta();
if (streamId > 0)
{
if (windowDelta == 0)
IStream stream = getStream(streamId);
if (stream != null)
{
reset(new ResetFrame(streamId, ErrorCode.PROTOCOL_ERROR.code), Callback.NOOP);
}
else
{
IStream stream = getStream(streamId);
if (stream != null)
int streamSendWindow = stream.updateSendWindow(0);
if (MathUtils.sumOverflows(streamSendWindow, windowDelta))
{
int streamSendWindow = stream.updateSendWindow(0);
if (sumOverflows(streamSendWindow, windowDelta))
{
reset(new ResetFrame(streamId, ErrorCode.FLOW_CONTROL_ERROR.code), Callback.NOOP);
}
else
{
stream.process(frame, Callback.NOOP);
onWindowUpdate(stream, frame);
}
reset(new ResetFrame(streamId, ErrorCode.FLOW_CONTROL_ERROR.code), Callback.NOOP);
}
else
{
if (!isRemoteStreamClosed(streamId))
onConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "unexpected_window_update_frame");
stream.process(frame, Callback.NOOP);
onWindowUpdate(stream, frame);
}
}
else
{
if (!isRemoteStreamClosed(streamId))
onConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "unexpected_window_update_frame");
}
}
else
{
if (windowDelta == 0)
{
onConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "invalid_window_update_frame");
}
int sessionSendWindow = updateSendWindow(0);
if (MathUtils.sumOverflows(sessionSendWindow, windowDelta))
onConnectionFailure(ErrorCode.FLOW_CONTROL_ERROR.code, "invalid_flow_control_window");
else
{
int sessionSendWindow = updateSendWindow(0);
if (sumOverflows(sessionSendWindow, windowDelta))
onConnectionFailure(ErrorCode.FLOW_CONTROL_ERROR.code, "invalid_flow_control_window");
else
onWindowUpdate(null, frame);
}
onWindowUpdate(null, frame);
}
}
@ -515,19 +502,6 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
callback.succeeded();
}
private boolean sumOverflows(int a, int b)
{
try
{
Math.addExact(a, b);
return false;
}
catch (ArithmeticException x)
{
return true;
}
}
@Override
public void onConnectionFailure(int error, String reason)
{

View File

@ -30,7 +30,7 @@ import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
/**
* <p>The SPI interface for implementing a HTTP/2 session.</p>
* <p>The SPI interface for implementing an HTTP/2 session.</p>
* <p>This class extends {@link Session} by adding the methods required to
* implement the HTTP/2 session functionalities.</p>
*/

View File

@ -25,7 +25,7 @@ import org.eclipse.jetty.http2.frames.Frame;
import org.eclipse.jetty.util.Callback;
/**
* <p>The SPI interface for implementing a HTTP/2 stream.</p>
* <p>The SPI interface for implementing an HTTP/2 stream.</p>
* <p>This class extends {@link Stream} by adding the methods required to
* implement the HTTP/2 stream functionalities.</p>
*/

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise;
/**
* <p>A {@link Session} represents the client-side endpoint of a HTTP/2 connection to a single origin server.</p>
* <p>A {@link Session} represents the client-side endpoint of an HTTP/2 connection to a single origin server.</p>
* <p>Once a {@link Session} has been obtained, it can be used to open HTTP/2 streams:</p>
* <pre>
* Session session = ...;
@ -127,7 +127,7 @@ public interface Session
/**
* <p>A {@link Listener} is the passive counterpart of a {@link Session} and
* receives events happening on a HTTP/2 connection.</p>
* receives events happening on an HTTP/2 connection.</p>
*
* @see Session
*/
@ -151,9 +151,9 @@ public interface Session
/**
* <p>Callback method invoked when a new stream is being created upon
* receiving a HEADERS frame representing a HTTP request.</p>
* receiving a HEADERS frame representing an HTTP request.</p>
* <p>Applications should implement this method to process HTTP requests,
* typically providing a HTTP response via
* typically providing an HTTP response via
* {@link Stream#headers(HeadersFrame, Callback)}.</p>
* <p>Applications can detect whether request DATA frames will be arriving
* by testing {@link HeadersFrame#isEndStream()}. If the application is

View File

@ -29,8 +29,8 @@ import org.eclipse.jetty.util.Promise;
* <p>A {@link Stream} represents a bidirectional exchange of data on top of a {@link Session}.</p>
* <p>Differently from socket streams, where the input and output streams are permanently associated
* with the socket (and hence with the connection that the socket represents), there can be multiple
* HTTP/2 streams present concurrent for a HTTP/2 session.</p>
* <p>A {@link Stream} maps to a HTTP request/response cycle, and after the request/response cycle is
* HTTP/2 streams present concurrent for an HTTP/2 session.</p>
* <p>A {@link Stream} maps to an HTTP request/response cycle, and after the request/response cycle is
* completed, the stream is closed and removed from the session.</p>
* <p>Like {@link Session}, {@link Stream} is the active part and by calling its API applications
* can generate events on the stream; conversely, {@link Stream.Listener} is the passive part, and
@ -51,7 +51,7 @@ public interface Stream
Session getSession();
/**
* <p>Sends the given HEADERS {@code frame} representing a HTTP response.</p>
* <p>Sends the given HEADERS {@code frame} representing an HTTP response.</p>
*
* @param frame the HEADERS frame to send
* @param callback the callback that gets notified when the frame has been sent
@ -131,7 +131,7 @@ public interface Stream
/**
* <p>A {@link Stream.Listener} is the passive counterpart of a {@link Stream} and receives
* events happening on a HTTP/2 stream.</p>
* events happening on an HTTP/2 stream.</p>
*
* @see Stream
*/

View File

@ -0,0 +1,48 @@
//
// ========================================================================
// Copyright (c) 1995-2019 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.http2.frames;
public class ContinuationFrame extends Frame
{
private final int streamId;
private final boolean endHeaders;
public ContinuationFrame(int streamId, boolean endHeaders)
{
super(FrameType.CONTINUATION);
this.streamId = streamId;
this.endHeaders = endHeaders;
}
public int getStreamId()
{
return streamId;
}
public boolean isEndHeaders()
{
return endHeaders;
}
@Override
public String toString()
{
return String.format("%s#%d{end=%b}", super.toString(), getStreamId(), isEndHeaders());
}
}

View File

@ -0,0 +1,36 @@
//
// ========================================================================
// Copyright (c) 1995-2019 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.http2.frames;
public class UnknownFrame extends Frame
{
private final int frameType;
public UnknownFrame(int frameType)
{
super(null);
this.frameType = frameType;
}
@Override
public String toString()
{
return String.format("%s,t=%d", super.toString(), frameType);
}
}

View File

@ -96,6 +96,11 @@ public abstract class BodyParser
return headerParser.getLength();
}
protected int getFrameType()
{
return headerParser.getFrameType();
}
protected void notifyData(DataFrame frame)
{
try
@ -223,9 +228,10 @@ public abstract class BodyParser
}
}
protected void streamFailure(int streamId, int error, String reason)
protected boolean streamFailure(int streamId, int error, String reason)
{
notifyStreamFailure(streamId, error, reason);
return false;
}
private void notifyStreamFailure(int streamId, int error, String reason)
@ -239,4 +245,9 @@ public abstract class BodyParser
LOG.info("Failure while notifying listener " + listener, x);
}
}
protected boolean rateControlOnEvent(Object o)
{
return headerParser.getRateControl().onEvent(o);
}
}

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.ErrorCode;
import org.eclipse.jetty.http2.Flags;
import org.eclipse.jetty.http2.frames.ContinuationFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
public class ContinuationBodyParser extends BodyParser
@ -43,7 +44,15 @@ public class ContinuationBodyParser extends BodyParser
protected void emptyBody(ByteBuffer buffer)
{
if (hasFlag(Flags.END_HEADERS))
onHeaders();
{
onHeaders(buffer);
}
else
{
ContinuationFrame frame = new ContinuationFrame(getStreamId(), hasFlag(Flags.END_HEADERS));
if (!rateControlOnEvent(frame))
connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_continuation_frame_rate");
}
}
@Override
@ -81,7 +90,7 @@ public class ContinuationBodyParser extends BodyParser
headerBlockFragments.storeFragment(buffer, length, last);
reset();
if (last)
return onHeaders();
return onHeaders(buffer);
return true;
}
}
@ -94,15 +103,20 @@ public class ContinuationBodyParser extends BodyParser
return false;
}
private boolean onHeaders()
private boolean onHeaders(ByteBuffer buffer)
{
ByteBuffer headerBlock = headerBlockFragments.complete();
MetaData metaData = headerBlockParser.parse(headerBlock, headerBlock.remaining());
if (metaData == null)
return true;
if (metaData == HeaderBlockParser.SESSION_FAILURE)
return false;
if (metaData == null || metaData == HeaderBlockParser.STREAM_FAILURE)
return true;
HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, headerBlockFragments.getPriorityFrame(), headerBlockFragments.isEndStream());
if (metaData == HeaderBlockParser.STREAM_FAILURE)
{
if (!rateControlOnEvent(frame))
return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_continuation_frame_rate");
}
notifyHeaders(frame);
return true;
}

View File

@ -48,9 +48,17 @@ public class DataBodyParser extends BodyParser
protected void emptyBody(ByteBuffer buffer)
{
if (isPadding())
{
connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_data_frame");
}
else
onData(BufferUtil.EMPTY_BUFFER, false, 0);
{
DataFrame frame = new DataFrame(getStreamId(), BufferUtil.EMPTY_BUFFER, isEndStream());
if (!isEndStream() && !rateControlOnEvent(frame))
connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_data_frame_rate");
else
onData(frame);
}
}
@Override
@ -134,7 +142,11 @@ public class DataBodyParser extends BodyParser
private void onData(ByteBuffer buffer, boolean fragment, int padding)
{
DataFrame frame = new DataFrame(getStreamId(), buffer, !fragment && isEndStream(), padding);
onData(new DataFrame(getStreamId(), buffer, !fragment && isEndStream(), padding));
}
private void onData(DataFrame frame)
{
notifyData(frame);
}

View File

@ -30,14 +30,24 @@ import org.eclipse.jetty.http2.frames.FrameType;
*/
public class HeaderParser
{
private final RateControl rateControl;
private State state = State.LENGTH;
private int cursor;
private int length;
private int type;
private int flags;
private int streamId;
public HeaderParser(RateControl rateControl)
{
this.rateControl = rateControl;
}
public RateControl getRateControl()
{
return rateControl;
}
protected void reset()
{
state = State.LENGTH;

View File

@ -61,17 +61,23 @@ public class HeadersBodyParser extends BodyParser
@Override
protected void emptyBody(ByteBuffer buffer)
{
if (hasFlag(Flags.END_HEADERS))
if (hasFlag(Flags.PRIORITY))
{
connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_headers_priority_frame");
}
else if (hasFlag(Flags.END_HEADERS))
{
MetaData metaData = headerBlockParser.parse(BufferUtil.EMPTY_BUFFER, 0);
onHeaders(0, 0, false, metaData);
HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, null, isEndStream());
if (!rateControlOnEvent(frame))
connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_headers_frame_rate");
else
onHeaders(frame);
}
else
{
headerBlockFragments.setStreamId(getStreamId());
headerBlockFragments.setEndStream(isEndStream());
if (hasFlag(Flags.PRIORITY))
connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_headers_priority_frame");
}
}
@ -179,7 +185,15 @@ public class HeadersBodyParser extends BodyParser
state = State.PADDING;
loop = paddingLength == 0;
if (metaData != HeaderBlockParser.STREAM_FAILURE)
{
onHeaders(parentStreamId, weight, exclusive, metaData);
}
else
{
HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, null, isEndStream());
if (!rateControlOnEvent(frame))
connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_headers_frame_rate");
}
}
}
else
@ -230,6 +244,11 @@ public class HeadersBodyParser extends BodyParser
if (hasFlag(Flags.PRIORITY))
priorityFrame = new PriorityFrame(getStreamId(), parentStreamId, weight, exclusive);
HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, priorityFrame, isEndStream());
onHeaders(frame);
}
private void onHeaders(HeadersFrame frame)
{
notifyHeaders(frame);
}

View File

@ -54,18 +54,22 @@ public class Parser
private final HpackDecoder hpackDecoder;
private final BodyParser[] bodyParsers;
private UnknownBodyParser unknownBodyParser;
private int maxFrameLength;
private int maxFrameLength = Frame.DEFAULT_MAX_LENGTH;
private int maxSettingsKeys = SettingsFrame.DEFAULT_MAX_KEYS;
private boolean continuation;
private State state = State.HEADER;
public Parser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize)
{
this(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize, RateControl.NO_RATE_CONTROL);
}
public Parser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl)
{
this.byteBufferPool = byteBufferPool;
this.listener = listener;
this.headerParser = new HeaderParser();
this.headerParser = new HeaderParser(rateControl == null ? RateControl.NO_RATE_CONTROL : rateControl);
this.hpackDecoder = new HpackDecoder(maxDynamicTableSize, maxHeaderSize);
this.maxFrameLength = Frame.DEFAULT_MAX_LENGTH;
this.bodyParsers = new BodyParser[FrameType.values().length];
}

View File

@ -66,7 +66,7 @@ public class PingBodyParser extends BodyParser
if (buffer.remaining() >= 8)
{
buffer.get(payload);
return onPing(payload);
return onPing(buffer, payload);
}
else
{
@ -80,7 +80,7 @@ public class PingBodyParser extends BodyParser
payload[8 - cursor] = buffer.get();
--cursor;
if (cursor == 0)
return onPing(payload);
return onPing(buffer, payload);
break;
}
default:
@ -92,9 +92,11 @@ public class PingBodyParser extends BodyParser
return false;
}
private boolean onPing(byte[] payload)
private boolean onPing(ByteBuffer buffer, byte[] payload)
{
PingFrame frame = new PingFrame(payload, hasFlag(Flags.ACK));
if (!rateControlOnEvent(frame))
return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_ping_frame_rate");
reset();
notifyPing(frame);
return true;

View File

@ -42,7 +42,7 @@ public class PrefaceParser
* <p>Advances this parser after the {@link PrefaceFrame#PREFACE_PREAMBLE_BYTES}.</p>
* <p>This allows the HTTP/1.1 parser to parse the preamble of the preface,
* which is a legal HTTP/1.1 request, and this parser will parse the remaining
* bytes, that are not parseable by a HTTP/1.1 parser.</p>
* bytes, that are not parseable by an HTTP/1.1 parser.</p>
*/
protected void directUpgrade()
{

View File

@ -103,7 +103,7 @@ public class PriorityBodyParser extends BodyParser
if (getStreamId() == parentStreamId)
return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_priority_frame");
int weight = (buffer.get() & 0xFF) + 1;
return onPriority(parentStreamId, weight, exclusive);
return onPriority(buffer, parentStreamId, weight, exclusive);
}
default:
{
@ -114,9 +114,11 @@ public class PriorityBodyParser extends BodyParser
return false;
}
private boolean onPriority(int parentStreamId, int weight, boolean exclusive)
private boolean onPriority(ByteBuffer buffer, int parentStreamId, int weight, boolean exclusive)
{
PriorityFrame frame = new PriorityFrame(getStreamId(), parentStreamId, weight, exclusive);
if (!rateControlOnEvent(frame))
return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_priority_frame_rate");
reset();
notifyPriority(frame);
return true;

View File

@ -0,0 +1,39 @@
//
// ========================================================================
// Copyright (c) 1995-2019 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.http2.parser;
/**
* Controls rate of events via {@link #onEvent(Object)}.
*/
public interface RateControl
{
public static final RateControl NO_RATE_CONTROL = event -> true;
/**
* <p>Applications should call this method when they want to signal an
* event that is subject to rate control.</p>
* <p>Implementations should return true if the event does not exceed
* the desired rate, or false to signal that the event exceeded the
* desired rate.</p>
*
* @param event the event subject to rate control.
* @return true IFF the rate is within limits
*/
public boolean onEvent(Object event);
}

View File

@ -37,9 +37,9 @@ public class ServerParser extends Parser
private State state = State.PREFACE;
private boolean notifyPreface = true;
public ServerParser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize)
public ServerParser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize, RateControl rateControl)
{
super(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize);
super(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize, rateControl);
this.listener = listener;
this.prefaceParser = new PrefaceParser(listener);
}

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.http2.parser;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@ -72,7 +73,12 @@ public class SettingsBodyParser extends BodyParser
@Override
protected void emptyBody(ByteBuffer buffer)
{
onSettings(buffer, new HashMap<>());
boolean isReply = hasFlag(Flags.ACK);
SettingsFrame frame = new SettingsFrame(Collections.emptyMap(), isReply);
if (!isReply && !rateControlOnEvent(frame))
connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_settings_frame_rate");
else
onSettings(frame);
}
@Override
@ -200,6 +206,11 @@ public class SettingsBodyParser extends BodyParser
return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_settings_max_frame_size");
SettingsFrame frame = new SettingsFrame(settings, hasFlag(Flags.ACK));
return onSettings(frame);
}
private boolean onSettings(SettingsFrame frame)
{
reset();
notifySettings(frame);
return true;
@ -207,40 +218,25 @@ public class SettingsBodyParser extends BodyParser
public static SettingsFrame parseBody(final ByteBuffer buffer)
{
final int bodyLength = buffer.remaining();
final AtomicReference<SettingsFrame> frameRef = new AtomicReference<>();
SettingsBodyParser parser = new SettingsBodyParser(null, null)
AtomicReference<SettingsFrame> frameRef = new AtomicReference<>();
SettingsBodyParser parser = new SettingsBodyParser(new HeaderParser(RateControl.NO_RATE_CONTROL), new Parser.Listener.Adapter()
{
@Override
protected int getStreamId()
public void onSettings(SettingsFrame frame)
{
return 0;
frameRef.set(frame);
}
@Override
protected int getBodyLength()
{
return bodyLength;
}
@Override
protected boolean onSettings(ByteBuffer buffer, Map<Integer, Integer> settings)
{
frameRef.set(new SettingsFrame(settings, false));
return true;
}
@Override
protected boolean connectionFailure(ByteBuffer buffer, int error, String reason)
public void onConnectionFailure(int error, String reason)
{
frameRef.set(null);
return false;
}
};
if (bodyLength == 0)
parser.emptyBody(buffer);
else
});
if (buffer.hasRemaining())
parser.parse(buffer);
else
parser.emptyBody(buffer);
return frameRef.get();
}

View File

@ -20,6 +20,9 @@ package org.eclipse.jetty.http2.parser;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http2.ErrorCode;
import org.eclipse.jetty.http2.frames.UnknownFrame;
public class UnknownBodyParser extends BodyParser
{
private int cursor;
@ -34,7 +37,11 @@ public class UnknownBodyParser extends BodyParser
{
int length = cursor == 0 ? getBodyLength() : cursor;
cursor = consume(buffer, length);
return cursor == 0;
boolean parsed = cursor == 0;
if (parsed && !rateControlOnEvent(new UnknownFrame(getFrameType())))
return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_unknown_frame_rate");
return parsed;
}
private int consume(ByteBuffer buffer, int length)

View File

@ -0,0 +1,65 @@
//
// ========================================================================
// Copyright (c) 1995-2019 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.http2.parser;
import java.time.Duration;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* <p>An implementation of {@link RateControl} that limits the number of
* events within a time period.</p>
* <p>Events are kept in a queue and for each event the queue is first
* drained of the old events outside the time window, and then the new
* event is added to the queue. The size of the queue is maintained
* separately in an AtomicInteger and if it exceeds the max
* number of events then {@link #onEvent(Object)} returns {@code false}.</p>
*/
public class WindowRateControl implements RateControl
{
private final Queue<Long> events = new ConcurrentLinkedQueue<>();
private final AtomicInteger size = new AtomicInteger();
private final int maxEvents;
private final long window;
public WindowRateControl(int maxEvents, Duration window)
{
this.maxEvents = maxEvents;
this.window = window.toNanos();
}
@Override
public boolean onEvent(Object event)
{
long now = System.nanoTime();
while (true)
{
Long time = events.peek();
if (time == null)
break;
if (now < time)
break;
if (events.remove(time))
size.decrementAndGet();
}
events.add(now + window);
return size.incrementAndGet() <= maxEvents;
}
}

View File

@ -61,7 +61,7 @@ public class WindowUpdateBodyParser extends BodyParser
if (buffer.remaining() >= 4)
{
windowDelta = buffer.getInt() & 0x7F_FF_FF_FF;
return onWindowUpdate(windowDelta);
return onWindowUpdate(buffer, windowDelta);
}
else
{
@ -78,7 +78,7 @@ public class WindowUpdateBodyParser extends BodyParser
if (cursor == 0)
{
windowDelta &= 0x7F_FF_FF_FF;
return onWindowUpdate(windowDelta);
return onWindowUpdate(buffer, windowDelta);
}
break;
}
@ -91,9 +91,17 @@ public class WindowUpdateBodyParser extends BodyParser
return false;
}
private boolean onWindowUpdate(int windowDelta)
private boolean onWindowUpdate(ByteBuffer buffer, int windowDelta)
{
WindowUpdateFrame frame = new WindowUpdateFrame(getStreamId(), windowDelta);
int streamId = getStreamId();
if (windowDelta == 0)
{
if (streamId == 0)
return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_window_update_frame");
else
return streamFailure(streamId, ErrorCode.PROTOCOL_ERROR.code, "invalid_window_update_frame");
}
WindowUpdateFrame frame = new WindowUpdateFrame(streamId, windowDelta);
reset();
notifyWindowUpdate(frame);
return true;

View File

@ -0,0 +1,161 @@
//
// ========================================================================
// Copyright (c) 1995-2019 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.http2.frames;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.UnaryOperator;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.Flags;
import org.eclipse.jetty.http2.hpack.HpackEncoder;
import org.eclipse.jetty.http2.parser.Parser;
import org.eclipse.jetty.http2.parser.WindowRateControl;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.lessThan;
public class FrameFloodTest
{
private final ByteBufferPool byteBufferPool = new MappedByteBufferPool();
// Frame structure:
// | Len0 | Len1 | Len2 | Type | Flags | StreamID0 |StreamID1 |StreamID2 |StreamID3 | Payload... |
private byte[] frameFrom(int length, int frameType, int flags, int streamId, byte[] payload)
{
byte[] result = new byte[3 + 1 + 1 + 4 + payload.length];
result[0] = (byte)((length >>> 16) & 0xFF);
result[1] = (byte)((length >>> 8) & 0xFF);
result[2] = (byte)(length & 0xFF);
result[3] = (byte)frameType;
result[4] = (byte)flags;
result[5] = (byte)((streamId >>> 24) & 0xFF);
result[6] = (byte)((streamId >>> 16) & 0xFF);
result[7] = (byte)((streamId >>> 8) & 0xFF);
result[8] = (byte)(streamId & 0xFF);
System.arraycopy(payload, 0, result, 9, payload.length);
return result;
}
@Test
public void testDataFrameFlood()
{
byte[] payload = new byte[0];
testFrameFlood(null, frameFrom(payload.length, FrameType.DATA.getType(), 0, 13, payload));
}
@Test
public void testHeadersFrameFlood()
{
byte[] payload = new byte[0];
testFrameFlood(null, frameFrom(payload.length, FrameType.HEADERS.getType(), Flags.END_HEADERS, 13, payload));
}
@Test
public void testInvalidHeadersFrameFlood()
{
// Invalid MetaData (no method, no scheme, etc).
MetaData.Request metadata = new MetaData.Request(null, (String)null, null, null, HttpVersion.HTTP_2, null, -1);
HpackEncoder encoder = new HpackEncoder();
ByteBuffer buffer = ByteBuffer.allocate(1024);
encoder.encode(buffer, metadata);
buffer.flip();
byte[] payload = new byte[buffer.remaining()];
buffer.get(payload);
testFrameFlood(null, frameFrom(payload.length, FrameType.HEADERS.getType(), Flags.END_HEADERS, 13, payload));
}
@Test
public void testPriorityFrameFlood()
{
byte[] payload = new byte[]{0, 0, 0, 7, 0};
testFrameFlood(null, frameFrom(payload.length, FrameType.PRIORITY.getType(), 0, 13, payload));
}
@Test
public void testSettingsFrameFlood()
{
byte[] payload = new byte[0];
testFrameFlood(null, frameFrom(payload.length, FrameType.SETTINGS.getType(), 0, 0, payload));
}
@Test
public void testPingFrameFlood()
{
byte[] payload = {0, 0, 0, 0, 0, 0, 0, 0};
testFrameFlood(null, frameFrom(payload.length, FrameType.PING.getType(), 0, 0, payload));
}
@Test
public void testContinuationFrameFlood()
{
int streamId = 13;
byte[] headersPayload = new byte[0];
byte[] headersBytes = frameFrom(headersPayload.length, FrameType.HEADERS.getType(), 0, streamId, headersPayload);
byte[] continuationPayload = new byte[0];
testFrameFlood(headersBytes, frameFrom(continuationPayload.length, FrameType.CONTINUATION.getType(), 0, streamId, continuationPayload));
}
@Test
public void testUnknownFrameFlood()
{
byte[] payload = {0, 0, 0, 0};
testFrameFlood(null, frameFrom(payload.length, 64, 0, 0, payload));
}
private void testFrameFlood(byte[] preamble, byte[] bytes)
{
AtomicBoolean failed = new AtomicBoolean();
Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter()
{
@Override
public void onConnectionFailure(int error, String reason)
{
failed.set(true);
}
}, 4096, 8192, new WindowRateControl(8, Duration.ofSeconds(1)));
parser.init(UnaryOperator.identity());
if (preamble != null)
{
ByteBuffer buffer = ByteBuffer.wrap(preamble);
while (buffer.hasRemaining())
{
parser.parse(buffer);
}
}
int count = 0;
while (!failed.get())
{
ByteBuffer buffer = ByteBuffer.wrap(bytes);
while (buffer.hasRemaining())
{
parser.parse(buffer);
}
assertThat("too many frames allowed", ++count, lessThan(1024));
}
}
}

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpTokens;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
import org.eclipse.jetty.util.TypeUtil;
@ -175,14 +176,35 @@ public class HpackDecoder
name = Huffman.decode(buffer, length);
else
name = toASCIIString(buffer, length);
for (int i = 0; i < name.length(); i++)
check:
for (int i = name.length(); i-- > 0;)
{
char c = name.charAt(i);
if (c >= 'A' && c <= 'Z')
if (c > 0xff)
{
_builder.streamException("Uppercase header name %s", name);
_builder.streamException("Illegal header name %s", name);
break;
}
HttpTokens.Token token = HttpTokens.TOKENS[0xFF & c];
switch (token.getType())
{
case ALPHA:
if (c >= 'A' && c <= 'Z')
{
_builder.streamException("Uppercase header name %s", name);
break check;
}
break;
case COLON:
case TCHAR:
case DIGIT:
break;
default:
_builder.streamException("Illegal header name %s", name);
break check;
}
}
header = HttpHeader.CACHE.get(name);
}

View File

@ -74,11 +74,13 @@ public class MetaDataBuilder
{
HttpHeader header = field.getHeader();
String name = field.getName();
if (name == null || name.length() == 0)
throw new HpackException.SessionException("Header size 0");
String value = field.getValue();
int fieldSize = name.length() + (value == null ? 0 : value.length());
_size += fieldSize + 32;
if (_size > _maxSize)
throw new HpackException.SessionException("Header Size %d > %d", _size, _maxSize);
throw new HpackException.SessionException("Header size %d > %d", _size, _maxSize);
if (field instanceof StaticTableHttpField)
{
@ -113,7 +115,7 @@ public class MetaDataBuilder
{
case C_STATUS:
if (checkPseudoHeader(header, _status))
_status = Integer.valueOf(field.getIntValue());
_status = field.getIntValue();
_response = true;
break;

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.hpack.HpackException.CompressionException;
import org.eclipse.jetty.http2.hpack.HpackException.SessionException;
import org.eclipse.jetty.http2.hpack.HpackException.StreamException;
import org.eclipse.jetty.util.TypeUtil;
import org.hamcrest.Matchers;
@ -43,6 +44,21 @@ import static org.junit.jupiter.api.Assertions.fail;
public class HpackDecoderTest
{
/*
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+-----------------------+
| H | Name Length (7+) |
+---+---------------------------+
| Name String (Length octets) |
+---+---------------------------+
| H | Value Length (7+) |
+---+---------------------------+
| Value String (Length octets) |
+-------------------------------+
*/
@Test
public void testDecodeD_3() throws Exception
{
@ -253,14 +269,14 @@ public class HpackDecoderTest
decoder.decode(buffer);
fail();
}
catch (HpackException.SessionException e)
catch (SessionException e)
{
assertThat(e.getMessage(), Matchers.startsWith("Unknown index"));
}
}
/* 8.1.2.1. Pseudo-Header Fields */
@Test()
@Test
public void test8_1_2_1_PsuedoHeaderFields() throws Exception
{
// 1:Sends a HEADERS frame that contains a unknown pseudo-header field
@ -312,7 +328,7 @@ public class HpackDecoderTest
}
}
@Test()
@Test
public void test8_1_2_2_ConnectionSpecificHeaderFields() throws Exception
{
MetaDataBuilder mdb;
@ -349,7 +365,7 @@ public class HpackDecoderTest
assertNotNull(mdb.build());
}
@Test()
@Test
public void test8_1_2_3_RequestPseudoHeaderFields() throws Exception
{
{
@ -368,7 +384,7 @@ public class HpackDecoderTest
mdb.emit(new HttpField(HttpHeader.C_SCHEME, "http"));
mdb.emit(new HttpField(HttpHeader.C_AUTHORITY, "localhost:8080"));
mdb.emit(new HttpField(HttpHeader.C_PATH, ""));
StreamException ex = assertThrows(StreamException.class, () -> mdb.build());
StreamException ex = assertThrows(StreamException.class, mdb::build);
assertThat(ex.getMessage(), Matchers.containsString("No Path"));
}
@ -378,7 +394,7 @@ public class HpackDecoderTest
mdb.emit(new HttpField(HttpHeader.C_SCHEME, "http"));
mdb.emit(new HttpField(HttpHeader.C_AUTHORITY, "localhost:8080"));
mdb.emit(new HttpField(HttpHeader.C_PATH, "/"));
StreamException ex = assertThrows(StreamException.class, () -> mdb.build());
StreamException ex = assertThrows(StreamException.class, mdb::build);
assertThat(ex.getMessage(), Matchers.containsString("No Method"));
}
@ -388,7 +404,7 @@ public class HpackDecoderTest
mdb.emit(new HttpField(HttpHeader.C_METHOD, "GET"));
mdb.emit(new HttpField(HttpHeader.C_AUTHORITY, "localhost:8080"));
mdb.emit(new HttpField(HttpHeader.C_PATH, "/"));
StreamException ex = assertThrows(StreamException.class, () -> mdb.build());
StreamException ex = assertThrows(StreamException.class, mdb::build);
assertThat(ex.getMessage(), Matchers.containsString("No Scheme"));
}
@ -398,7 +414,7 @@ public class HpackDecoderTest
mdb.emit(new HttpField(HttpHeader.C_METHOD, "GET"));
mdb.emit(new HttpField(HttpHeader.C_SCHEME, "http"));
mdb.emit(new HttpField(HttpHeader.C_AUTHORITY, "localhost:8080"));
StreamException ex = assertThrows(StreamException.class, () -> mdb.build());
StreamException ex = assertThrows(StreamException.class, mdb::build);
assertThat(ex.getMessage(), Matchers.containsString("No Path"));
}
@ -410,7 +426,7 @@ public class HpackDecoderTest
mdb.emit(new HttpField(HttpHeader.C_SCHEME, "http"));
mdb.emit(new HttpField(HttpHeader.C_AUTHORITY, "localhost:8080"));
mdb.emit(new HttpField(HttpHeader.C_PATH, "/"));
StreamException ex = assertThrows(StreamException.class, () -> mdb.build());
StreamException ex = assertThrows(StreamException.class, mdb::build);
assertThat(ex.getMessage(), Matchers.containsString("Duplicate"));
}
@ -423,12 +439,12 @@ public class HpackDecoderTest
mdb.emit(new HttpField(HttpHeader.C_AUTHORITY, "localhost:8080"));
mdb.emit(new HttpField(HttpHeader.C_PATH, "/"));
StreamException ex = assertThrows(StreamException.class, () -> mdb.build());
StreamException ex = assertThrows(StreamException.class, mdb::build);
assertThat(ex.getMessage(), Matchers.containsString("Duplicate"));
}
}
@Test()
@Test
public void testHuffmanEncodedStandard() throws Exception
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
@ -446,8 +462,8 @@ public class HpackDecoderTest
}
/* 5.2.1: Sends a Huffman-encoded string literal representation with padding longer than 7 bits */
@Test()
public void testHuffmanEncodedExtraPadding() throws Exception
@Test
public void testHuffmanEncodedExtraPadding()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
@ -458,8 +474,8 @@ public class HpackDecoderTest
}
/* 5.2.2: Sends a Huffman-encoded string literal representation padded by zero */
@Test()
public void testHuffmanEncodedZeroPadding() throws Exception
@Test
public void testHuffmanEncodedZeroPadding()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
@ -471,8 +487,8 @@ public class HpackDecoderTest
}
/* 5.2.3: Sends a Huffman-encoded string literal representation containing the EOS symbol */
@Test()
public void testHuffmanEncodedWithEOS() throws Exception
@Test
public void testHuffmanEncodedWithEOS()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
@ -483,8 +499,8 @@ public class HpackDecoderTest
assertThat(ex.getMessage(), Matchers.containsString("EOS in content"));
}
@Test()
public void testHuffmanEncodedOneIncompleteOctet() throws Exception
@Test
public void testHuffmanEncodedOneIncompleteOctet()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
@ -495,8 +511,8 @@ public class HpackDecoderTest
assertThat(ex.getMessage(), Matchers.containsString("Bad termination"));
}
@Test()
public void testHuffmanEncodedTwoIncompleteOctet() throws Exception
@Test
public void testHuffmanEncodedTwoIncompleteOctet()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
@ -506,4 +522,49 @@ public class HpackDecoderTest
CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Bad termination"));
}
@Test
public void testZeroLengthName()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
String encoded = "00000130";
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
SessionException ex = assertThrows(SessionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Header size 0"));
}
@Test
public void testZeroLengthValue() throws Exception
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
String encoded = "00016800";
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
MetaData metaData = decoder.decode(buffer);
assertThat(metaData.getFields().size(), is(1));
assertThat(metaData.getFields().get("h"), is(""));
}
@Test
public void testUpperCaseName()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
String encoded = "0001480130";
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
StreamException ex = assertThrows(StreamException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Uppercase header"));
}
@Test
public void testWhiteSpaceName()
{
HpackDecoder decoder = new HpackDecoder(4096, 8192);
String encoded = "0001200130";
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
StreamException ex = assertThrows(StreamException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Illegal header"));
}
}

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.http2.client.http;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
@ -38,7 +37,6 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.UnaryOperator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -63,6 +61,7 @@ import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.ResetFrame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.http2.generator.Generator;
import org.eclipse.jetty.http2.parser.RateControl;
import org.eclipse.jetty.http2.parser.ServerParser;
import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory;
import org.eclipse.jetty.io.ByteBufferPool;
@ -187,7 +186,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
{
baseRequest.setHandled(true);
HttpVersion version = HttpVersion.fromString(request.getProtocol());
@ -199,7 +198,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
.onRequestBegin(request ->
{
if (request.getVersion() != HttpVersion.HTTP_2)
request.abort(new Exception("Not a HTTP/2 request"));
request.abort(new Exception("Not an HTTP/2 request"));
})
.send();
@ -313,7 +312,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
{
baseRequest.setHandled(true);
assertEquals(path, request.getRequestURI());
@ -337,7 +336,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
{
baseRequest.setHandled(true);
assertEquals(path, request.getRequestURI());
@ -501,7 +500,7 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
x.printStackTrace();
}
}
}, 4096, 8192);
}, 4096, 8192, RateControl.NO_RATE_CONTROL);
parser.init(UnaryOperator.identity());
byte[] bytes = new byte[1024];

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure a HTTP2 on the ssl connector. --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure an HTTP2 on the ssl connector. --><!-- ============================================================= -->
<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
<Call name="addConnectionFactory">
<Arg>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure a HTTP2 on the ssl connector. --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure an HTTP2 on the ssl connector. --><!-- ============================================================= -->
<Configure id="httpConnector" class="org.eclipse.jetty.server.ServerConnector">
<Call name="addConnectionFactory">
<Arg>

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.http2.server;
import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -34,7 +35,9 @@ import org.eclipse.jetty.http2.api.server.ServerSessionListener;
import org.eclipse.jetty.http2.frames.Frame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.http2.generator.Generator;
import org.eclipse.jetty.http2.parser.RateControl;
import org.eclipse.jetty.http2.parser.ServerParser;
import org.eclipse.jetty.http2.parser.WindowRateControl;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.AbstractConnectionFactory;
@ -58,6 +61,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
private int maxHeaderBlockFragment = 0;
private int maxFrameLength = Frame.DEFAULT_MAX_LENGTH;
private int maxSettingsKeys = SettingsFrame.DEFAULT_MAX_KEYS;
private RateControl rateControl = new WindowRateControl(20, Duration.ofSeconds(1));
private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
private long streamIdleTimeout;
@ -178,6 +182,16 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
this.maxSettingsKeys = maxSettingsKeys;
}
public RateControl getRateControl()
{
return rateControl;
}
public void setRateControl(RateControl rateControl)
{
this.rateControl = rateControl;
}
/**
* @return -1
* @deprecated feature removed, no replacement
@ -237,7 +251,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
session.setWriteThreshold(getHttpConfiguration().getOutputBufferSize());
ServerParser parser = newServerParser(connector, session);
ServerParser parser = newServerParser(connector, session, getRateControl());
parser.setMaxFrameLength(getMaxFrameLength());
parser.setMaxSettingsKeys(getMaxSettingsKeys());
@ -249,9 +263,9 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint);
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener)
protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener, RateControl rateControl)
{
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize(), rateControl);
}
@ManagedObject("The container of HTTP/2 sessions")

View File

@ -39,8 +39,8 @@ import org.eclipse.jetty.util.log.Logger;
* </p>
* <p>If used in combination with a {@link HttpConnectionFactory} as the
* default protocol, this factory can support the non-standard direct
* update mechanism, where a HTTP1 request of the form "PRI * HTTP/2.0"
* is used to trigger a switch to a HTTP2 connection. This approach
* update mechanism, where an HTTP1 request of the form "PRI * HTTP/2.0"
* is used to trigger a switch to an HTTP2 connection. This approach
* allows a single port to accept either HTTP/1 or HTTP/2 direct
* connections.
*/

View File

@ -64,7 +64,7 @@ import org.eclipse.jetty.util.TypeUtil;
public class HTTP2ServerConnection extends HTTP2Connection implements Connection.UpgradeTo
{
/**
* @param protocol A HTTP2 protocol variant
* @param protocol An HTTP2 protocol variant
* @return True if the protocol version is supported
*/
public static boolean isSupportedProtocol(String protocol)

View File

@ -188,7 +188,7 @@ public class HTTP2CServerTest extends AbstractServerTest
assertThat(content, containsString("Hello from Jetty using HTTP/1.1"));
assertThat(content, containsString("uri=/one"));
// Send a HTTP/2 request.
// Send an HTTP/2 request.
headersRef.set(null);
dataRef.set(null);
latchRef.set(new CountDownLatch(2));
@ -319,7 +319,7 @@ public class HTTP2CServerTest extends AbstractServerTest
connector.setDefaultProtocol(connectionFactory.getProtocol());
connector.start();
// Now send a HTTP/2 direct request, which
// Now send an HTTP/2 direct request, which
// will have the PRI * HTTP/2.0 preface.
byteBufferPool = new MappedByteBufferPool();
@ -336,7 +336,7 @@ public class HTTP2CServerTest extends AbstractServerTest
output.write(BufferUtil.toArray(buffer));
}
// We sent a HTTP/2 preface, but the server has no "h2c" connection
// We sent an HTTP/2 preface, but the server has no "h2c" connection
// factory so it does not know how to handle this request.
InputStream input = client.getInputStream();

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure a HTTP2 on the ssl connector. --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure an HTTP2 on the ssl connector. --><!-- ============================================================= -->
<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
<Call name="addConnectionFactory">
<Arg>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure a HTTP2 on the ssl connector. --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure an HTTP2 on the ssl connector. --><!-- ============================================================= -->
<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
<Call name="addConnectionFactory">
<Arg>

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure a HTTPS connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- and jetty-ssl.xml. --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure an HTTPS connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- and jetty-ssl.xml. --><!-- ============================================================= -->
<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
<Call name="addIfAbsentConnectionFactory">

View File

@ -9,7 +9,7 @@
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a SSL Connector with no protocol factories -->
<!-- Add an SSL Connector with no protocol factories -->
<!-- =========================================================== -->
<Call name="addConnector">
<Arg>

View File

@ -40,7 +40,7 @@
</Call>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- To add a HTTPS SSL listener -->
<!-- To add an HTTPS SSL listener -->
<!-- see jetty-ssl.xml to add an ssl connector. use -->
<!-- java -jar start.jar etc/jetty-ssl.xml -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

View File

@ -51,7 +51,7 @@ import org.ietf.jgss.Oid;
* of the {@link #getServiceName() service name} and the {@link #getHostName() host name},
* for example {@code HTTP/wonder.com}, using a {@code keyTab} file as the service principal
* credentials.</p>
* <p>Upon receiving a HTTP request, the server tries to authenticate the client
* <p>Upon receiving an HTTP request, the server tries to authenticate the client
* calling {@link #login(String, Object, ServletRequest)} where the GSS APIs are used to
* verify client tokens and (perhaps after a few round-trips) a {@code GSSContext} is
* established.</p>

View File

@ -806,7 +806,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
{
//an exact method name
if (!hasOmissions)
//a http-method does not have http-method-omission to cover the other method names
//an http-method does not have http-method-omission to cover the other method names
uncoveredPaths.add(path);
}
}

View File

@ -39,7 +39,7 @@ import org.eclipse.jetty.util.log.Logger;
*
* When a user has been successfully authenticated with some types
* of Authenticator, the Authenticator stashes a SessionAuthentication
* into a HttpSession to remember that the user is authenticated.
* into an HttpSession to remember that the user is authenticated.
*/
public class SessionAuthentication extends AbstractUserAuthentication
implements Serializable, HttpSessionActivationListener, HttpSessionBindingListener

View File

@ -423,7 +423,7 @@ public class ConstraintTest
assertEquals(1, uncoveredPaths.size());
assertThat("/user/*", is(in(uncoveredPaths)));
//Test an explicitly named method with a http-method-omission to cover all other methods
//Test an explicitly named method with an http-method-omission to cover all other methods
Constraint constraint2a = new Constraint();
constraint2a.setAuthenticate(true);
constraint2a.setName("forbid constraint");
@ -437,7 +437,7 @@ public class ConstraintTest
assertNotNull(uncoveredPaths);
assertEquals(0, uncoveredPaths.size());
//Test a http-method-omission only
//Test an http-method-omission only
Constraint constraint3 = new Constraint();
constraint3.setAuthenticate(true);
constraint3.setName("omit constraint");

View File

@ -1,10 +1,10 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding a HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a HTTP Connector. -->
<!-- Add an HTTP Connector. -->
<!-- Configure an o.e.j.server.ServerConnector with a single -->
<!-- HttpConnectionFactory instance using the common httpConfig -->
<!-- instance defined in jetty.xml -->

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ============================================================= --><!-- Configure a HTTPS connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- and jetty-ssl.xml. --><!-- ============================================================= -->
<!-- ============================================================= --><!-- Configure an HTTPS connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- and jetty-ssl.xml. --><!-- ============================================================= -->
<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
<Call name="addIfAbsentConnectionFactory">

View File

@ -4,7 +4,7 @@
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- Add a SSL Connector with no protocol factories -->
<!-- Add an SSL Connector with no protocol factories -->
<!-- =========================================================== -->
<Call name="addConnector">
<Arg>

View File

@ -1,7 +1,7 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enables a HTTP connector on the server.
Enables an HTTP connector on the server.
By default HTTP/1 is support, but HTTP2C can
be added to the connector with the http2c module.

View File

@ -116,7 +116,7 @@ import org.eclipse.jetty.util.thread.ThreadPoolBudget;
* {@link ConnectionFactory}s may also create temporary {@link org.eclipse.jetty.io.Connection} instances that will exchange bytes
* over the connection to determine what is the next protocol to use. For example the ALPN protocol is an extension
* of SSL to allow a protocol to be specified during the SSL handshake. ALPN is used by the HTTP/2 protocol to
* negotiate the protocol that the client and server will speak. Thus to accept a HTTP/2 connection, the
* negotiate the protocol that the client and server will speak. Thus to accept an HTTP/2 connection, the
* connector will be configured with {@link ConnectionFactory}s for "SSL-ALPN", "h2", "http/1.1"
* with the default protocol being "SSL-ALPN". Thus a newly accepted connection uses "SSL-ALPN", which specifies a
* SSLConnectionFactory with "ALPN" as the next protocol. Thus an SSL connection instance is created chained to an ALPN

View File

@ -35,11 +35,11 @@ import org.eclipse.jetty.io.EndPoint;
* A ConnectionFactory has a protocol name that represents the protocol of the Connections
* created. Example of protocol names include:
* <dl>
* <dt>http</dt><dd>Creates a HTTP connection that can handle multiple versions of HTTP from 0.9 to 1.1</dd>
* <dt>h2</dt><dd>Creates a HTTP/2 connection that handles the HTTP/2 protocol</dd>
* <dt>http</dt><dd>Creates an HTTP connection that can handle multiple versions of HTTP from 0.9 to 1.1</dd>
* <dt>h2</dt><dd>Creates an HTTP/2 connection that handles the HTTP/2 protocol</dd>
* <dt>SSL-XYZ</dt><dd>Create an SSL connection chained to a connection obtained from a connection factory
* with a protocol "XYZ".</dd>
* <dt>SSL-http</dt><dd>Create an SSL connection chained to a HTTP connection (aka https)</dd>
* <dt>SSL-http</dt><dd>Create an SSL connection chained to an HTTP connection (aka https)</dd>
* <dt>SSL-ALPN</dt><dd>Create an SSL connection chained to a ALPN connection, that uses a negotiation with
* the client to determine the next protocol.</dd>
* </dl>

View File

@ -352,7 +352,7 @@ public class ForwardedRequestCustomizer implements Customizer
}
/**
* @return true if the presence of a SSL session or certificate header is sufficient
* @return true if the presence of an SSL session or certificate header is sufficient
* to indicate a secure request (default is true)
*/
public boolean isSslIsSecure()
@ -361,7 +361,7 @@ public class ForwardedRequestCustomizer implements Customizer
}
/**
* @param sslIsSecure true if the presence of a SSL session or certificate header is sufficient
* @param sslIsSecure true if the presence of an SSL session or certificate header is sufficient
* to indicate a secure request (default is true)
*/
public void setSslIsSecure(boolean sslIsSecure)
@ -630,16 +630,16 @@ public class ForwardedRequestCustomizer implements Customizer
if (!getForwardedPortAsAuthority())
{
if (_for == null)
_for = new PortSetHostPort(_request.getRemoteHost(), field.getIntValue());
_for = new PortSetHostPort(_request.getRemoteHost(), Integer.parseInt(getLeftMost(field.getValue())));
else if (_for instanceof PossiblyPartialHostPort && _for.getPort() <= 0)
_for = new HostPort(HostPort.normalizeHost(_for.getHost()), field.getIntValue());
_for = new HostPort(HostPort.normalizeHost(_for.getHost()), Integer.parseInt(getLeftMost(field.getValue())));
}
else
{
if (_host == null)
_host = new PortSetHostPort(_request.getServerName(), field.getIntValue());
_host = new PortSetHostPort(_request.getServerName(), Integer.parseInt(getLeftMost(field.getValue())));
else if (_host instanceof PossiblyPartialHostPort && _host.getPort() <= 0)
_host = new HostPort(HostPort.normalizeHost(_host.getHost()), field.getIntValue());
_host = new HostPort(HostPort.normalizeHost(_host.getHost()), Integer.parseInt(getLeftMost(field.getValue())));
}
}

View File

@ -61,7 +61,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
/**
* HttpChannel represents a single endpoint for HTTP semantic processing.
* The HttpChannel is both a HttpParser.RequestHandler, where it passively receives events from
* The HttpChannel is both an HttpParser.RequestHandler, where it passively receives events from
* an incoming HTTP request, and a Runnable, where it actively takes control of the request/response
* life cycle and calls the application (perhaps suspending and resuming with multiple calls to run).
* The HttpChannel signals the switch from passive mode to active mode by returning true to one of the
@ -1016,7 +1016,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
/**
* <p>Listener for {@link HttpChannel} events.</p>
* <p>HttpChannel will emit events for the various phases it goes through while
* processing a HTTP request and response.</p>
* processing an HTTP request and response.</p>
* <p>Implementations of this interface may listen to those events to track
* timing and/or other values such as request URI, etc.</p>
* <p>The events parameters, especially the {@link Request} object, may be

View File

@ -44,7 +44,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* A HttpChannel customized to be transported over the HTTP/1 protocol
* An HttpChannel customized to be transported over the HTTP/1 protocol
*/
public class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandler, HttpParser.ComplianceHandler
{
@ -411,7 +411,7 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque
}
/**
* <p>Attempts to perform a HTTP/1.1 upgrade.</p>
* <p>Attempts to perform an HTTP/1.1 upgrade.</p>
* <p>The upgrade looks up a {@link ConnectionFactory.Upgrading} from the connector
* matching the protocol specified in the {@code Upgrade} header.</p>
* <p>The upgrade may succeed, be ignored (which can allow a later handler to implement)

View File

@ -39,7 +39,7 @@ import org.eclipse.jetty.util.log.Logger;
/**
* HTTP Configuration.
* <p>This class is a holder of HTTP configuration for use by the
* {@link HttpChannel} class. Typically a HTTPConfiguration instance
* {@link HttpChannel} class. Typically an HTTPConfiguration instance
* is instantiated and passed to a {@link ConnectionFactory} that can
* create HTTP channels (e.g. HTTP, AJP or FCGI).</p>
* <p>The configuration held by this class is not for the wire protocol,
@ -184,19 +184,19 @@ public class HttpConfiguration implements Dumpable
return _outputAggregationSize;
}
@ManagedAttribute("The maximum allowed size in bytes for a HTTP request header")
@ManagedAttribute("The maximum allowed size in bytes for an HTTP request header")
public int getRequestHeaderSize()
{
return _requestHeaderSize;
}
@ManagedAttribute("The maximum allowed size in bytes for a HTTP response header")
@ManagedAttribute("The maximum allowed size in bytes for an HTTP response header")
public int getResponseHeaderSize()
{
return _responseHeaderSize;
}
@ManagedAttribute("The maximum allowed size in bytes for a HTTP header field cache")
@ManagedAttribute("The maximum allowed size in bytes for an HTTP header field cache")
public int getHeaderCacheSize()
{
return _headerCacheSize;
@ -221,20 +221,20 @@ public class HttpConfiguration implements Dumpable
}
/**
* <p>The max idle time is applied to a HTTP request for IO operations and
* <p>The max idle time is applied to an HTTP request for IO operations and
* delayed dispatch.</p>
*
* @return the max idle time in ms or if == 0 implies an infinite timeout, &lt;0
* implies no HTTP channel timeout and the connection timeout is used instead.
*/
@ManagedAttribute("The idle timeout in ms for I/O operations during the handling of a HTTP request")
@ManagedAttribute("The idle timeout in ms for I/O operations during the handling of an HTTP request")
public long getIdleTimeout()
{
return _idleTimeout;
}
/**
* <p>The max idle time is applied to a HTTP request for IO operations and
* <p>The max idle time is applied to an HTTP request for IO operations and
* delayed dispatch.</p>
*
* @param timeoutMs the max idle time in ms or if == 0 implies an infinite timeout, &lt;0

View File

@ -95,7 +95,7 @@ public class OptionalSslConnectionFactory extends AbstractConnectionFactory
int byte2 = buffer.get(1) & 0xFF;
if (byte1 == 'G' && byte2 == 'E')
{
// Plain text HTTP to a HTTPS port,
// Plain text HTTP to an HTTPS port,
// write a minimal response.
String body =
"<!DOCTYPE html>\r\n" +

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceFactory;
/**
* A HttpContent.Factory for transient content (not cached). The HttpContent's created by
* An HttpContent.Factory for transient content (not cached). The HttpContent's created by
* this factory are not intended to be cached, so memory limits for individual
* HttpOutput streams are enforced.
*/

View File

@ -410,7 +410,7 @@ public class Response implements HttpServletResponse
/**
* Sends a 102-Processing response.
* If the connection is a HTTP connection, the version is 1.1 and the
* If the connection is an HTTP connection, the version is 1.1 and the
* request has a Expect header starting with 102, then a 102 response is
* sent. This indicates that the request still be processed and real response
* can still be sent. This method is called by sendError if it is passed 102.

View File

@ -35,7 +35,7 @@ import javax.servlet.http.Part;
/**
* ServletRequestHttpWrapper
*
* Class to tunnel a ServletRequest via a HttpServletRequest
* Class to tunnel a ServletRequest via an HttpServletRequest
*/
public class ServletRequestHttpWrapper extends ServletRequestWrapper implements HttpServletRequest
{

View File

@ -28,7 +28,7 @@ import javax.servlet.http.HttpServletResponse;
/**
* ServletResponseHttpWrapper
*
* Wrapper to tunnel a ServletResponse via a HttpServletResponse
* Wrapper to tunnel a ServletResponse via an HttpServletResponse
*/
public class ServletResponseHttpWrapper extends ServletResponseWrapper implements HttpServletResponse
{

View File

@ -50,7 +50,7 @@ import org.eclipse.jetty.util.log.Logger;
* Handler for Error pages
* An ErrorHandler is registered with {@link ContextHandler#setErrorHandler(ErrorHandler)} or
* {@link Server#setErrorHandler(ErrorHandler)}.
* It is called by the HttpResponse.sendError method to write a error page via {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)}
* It is called by the HttpResponse.sendError method to write an error page via {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)}
* or via {@link #badMessageError(int, String, HttpFields)} for bad requests for which a dispatch cannot be done.
*/
public class ErrorHandler extends AbstractHandler
@ -467,7 +467,7 @@ public class ErrorHandler extends AbstractHandler
/**
* Bad Message Error body
* <p>Generate a error response body to be sent for a bad message.
* <p>Generate an error response body to be sent for a bad message.
* In this case there is something wrong with the request, so either
* a request cannot be built, or it is not safe to build a request.
* This method allows for a simple error page body to be returned

View File

@ -38,7 +38,7 @@ import org.eclipse.jetty.util.log.Logger;
* A handler that shuts the server down on a valid request. Used to do "soft" restarts from Java.
* If _exitJvm is set to true a hard System.exit() call is being made.
* If _sendShutdownAtStart is set to true, starting the server will try to shut down an existing server at the same port.
* If _sendShutdownAtStart is set to true, make a http call to
* If _sendShutdownAtStart is set to true, make an http call to
* "http://localhost:" + port + "/shutdown?token=" + shutdownCookie
* in order to shut down the server.
*
@ -100,7 +100,7 @@ public class ShutdownHandler extends HandlerWrapper
/**
* @param shutdownToken a secret password to avoid unauthorized shutdown attempts
* @param exitJVM If true, when the shutdown is executed, the handler class System.exit()
* @param sendShutdownAtStart If true, a shutdown is sent as a HTTP post
* @param sendShutdownAtStart If true, a shutdown is sent as an HTTP post
* during startup, which will shutdown any previously running instances of
* this server with an identically configured ShutdownHandler
*/

View File

@ -27,7 +27,7 @@ import org.eclipse.jetty.server.HttpInput.Content;
import org.eclipse.jetty.util.component.Destroyable;
/**
* A HttpInput Interceptor that inflates GZIP encoded request content.
* An HttpInput Interceptor that inflates GZIP encoded request content.
*/
public class GzipHttpInputInterceptor implements HttpInput.Interceptor, Destroyable
{

View File

@ -42,7 +42,7 @@ import org.eclipse.jetty.util.thread.Locker.Lock;
/**
* Session
*
* A heavy-weight Session object representing a HttpSession. Session objects
* A heavy-weight Session object representing an HttpSession. Session objects
* relating to a context are kept in a {@link SessionCache}. The purpose of the
* SessionCache is to keep the working set of Session objects in memory so that
* they may be accessed quickly, and facilitate the sharing of a Session object

View File

@ -555,7 +555,7 @@ public class SessionHandler extends ScopedHandler
/**
* @return same as SessionCookieConfig.getSecure(). If true, session
* cookies are ALWAYS marked as secure. If false, a session cookie is
* ONLY marked as secure if _secureRequestOnly == true and it is a HTTPS request.
* ONLY marked as secure if _secureRequestOnly == true and it is an HTTPS request.
*/
@ManagedAttribute("if true, secure cookie flag is set on session cookies")
public boolean getSecureCookies()

View File

@ -348,6 +348,18 @@ public class ForwardedRequestCustomizerTest
.requestURL("http://myhost:2222/")
.remoteAddr("[1:2:3:4:5:6:7:8]").remotePort(0)
),
Arguments.of(new Request("X-Forwarded-For and X-Forwarded-Port (multiple times combined)")
.headers(
"GET / HTTP/1.1",
"Host: myhost",
"X-Forwarded-Port: 2222, 3333",
"X-Forwarded-For: 1:2:3:4:5:6:7:8, 7:7:7:7:7:7:7:7"
),
new Expectations()
.scheme("http").serverName("myhost").serverPort(2222)
.requestURL("http://myhost:2222/")
.remoteAddr("[1:2:3:4:5:6:7:8]").remotePort(0)
),
Arguments.of(new Request("X-Forwarded-Port")
.headers(
"GET / HTTP/1.1",

Some files were not shown because too many files have changed in this diff Show More