From 4f19e6b638b3b11e0c787a6fab27abce1b079cba Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 31 Oct 2019 15:56:24 +0100 Subject: [PATCH 1/5] Fixes #4251 - Http 2.0 clients cannot upgrade protocol in 9.4.22 release. Fixed HTTP2-Settings header parsing. Signed-off-by: Simone Bordet --- .../jetty/http2/parser/SettingsBodyParser.java | 11 ++++++++--- .../eclipse/jetty/http2/server/HTTP2CServerTest.java | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java index b58fa8a8b51..5ca509f1271 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java @@ -83,6 +83,11 @@ public class SettingsBodyParser extends BodyParser @Override public boolean parse(ByteBuffer buffer) + { + return parse(buffer, getStreamId(), getBodyLength()); + } + + private boolean parse(ByteBuffer buffer, int streamId, int bodyLength) { while (buffer.hasRemaining()) { @@ -91,9 +96,9 @@ public class SettingsBodyParser extends BodyParser case PREPARE: { // SPEC: wrong streamId is treated as connection error. - if (getStreamId() != 0) + if (streamId != 0) return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_settings_frame"); - length = getBodyLength(); + length = bodyLength; settings = new HashMap<>(); state = State.SETTING_ID; break; @@ -234,7 +239,7 @@ public class SettingsBodyParser extends BodyParser } }); if (buffer.hasRemaining()) - parser.parse(buffer); + parser.parse(buffer, 0, buffer.remaining()); else parser.emptyBody(buffer); return frameRef.get(); diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java index 48552abebac..0dbfd503e0d 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java @@ -125,7 +125,7 @@ public class HTTP2CServerTest extends AbstractServerTest "Host: localhost\r\n" + "Connection: something, else, upgrade, HTTP2-Settings\r\n" + "Upgrade: h2c\r\n" + - "HTTP2-Settings: \r\n" + + "HTTP2-Settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA\r\n" + "\r\n").getBytes(StandardCharsets.ISO_8859_1)); output.flush(); From 3ae9faab79319ce6dd8ff61fdc1d8f322f42fc46 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 31 Oct 2019 22:24:31 +0100 Subject: [PATCH 2/5] Fixes #4251 - Http 2.0 clients cannot upgrade protocol in 9.4.22 release. Updates after review. Signed-off-by: Simone Bordet --- .../org/eclipse/jetty/http2/parser/SettingsBodyParser.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java index 5ca509f1271..49401e5e45d 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java @@ -221,6 +221,13 @@ public class SettingsBodyParser extends BodyParser return true; } + /** + *

Parses the given buffer containing the whole body of a {@code SETTINGS} frame + * (without header bytes), typically from the {@code HTTP2-Settings} header.

+ * + * @param buffer the buffer containing the body of {@code SETTINGS} frame + * @return the {@code SETTINGS} frame from the parsed body bytes + */ public static SettingsFrame parseBody(final ByteBuffer buffer) { AtomicReference frameRef = new AtomicReference<>(); From 9cede68b355515e1cf8802fd1fcf67aa7547aad1 Mon Sep 17 00:00:00 2001 From: Julien Gouesse Date: Sat, 5 Aug 2017 21:24:46 +0200 Subject: [PATCH 3/5] Add systemd service file #1485 Signed-off-by: Julien Gouesse --- jetty-home/src/main/resources/bin/jetty.service | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 jetty-home/src/main/resources/bin/jetty.service diff --git a/jetty-home/src/main/resources/bin/jetty.service b/jetty-home/src/main/resources/bin/jetty.service new file mode 100644 index 00000000000..4d4ace56db0 --- /dev/null +++ b/jetty-home/src/main/resources/bin/jetty.service @@ -0,0 +1,15 @@ +[Unit] +Description=Jetty Web Application Server +After=syslog.target network.target remote-fs.target nss-lookup.target + +[Service] +Type=forking +PIDFile=/opt/web/mybase/jetty.pid +ExecStart=/etc/init.d/jetty start +ExecStop=/etc/init.d/jetty stop +ExecReload=/etc/init.d/jetty restart +User=jetty +Group=jetty + +[Install] +WantedBy=multi-user.target From 869c3b51ce74a5d50a4c90e5136945e729bf55d1 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 5 Nov 2019 08:45:46 +1100 Subject: [PATCH 4/5] Issue #4265 Remove doError (#4266) * Issue #4265 Remove doError The doError method and the ErrorDispatchHandler class were hang overs from when we needed to dispatch into a context to get sendError called, which would then generate the error page. Now sendError doesn't do any generation, rather it changes state that arranges either for a minimal error page to be generated or an ERROR dispatch to a real handler/servlet to generate the error page. Thus the ErrorDispatchHandler and doError methods can now be removed. Signed-off-by: Greg Wilkins * Issue #4265 Remove doError Moved the error page dispatching logic back to the ErrorHandler class to assist with backwards compatibility Signed-off-by: Greg Wilkins * Issue #4265 Remove doError Moved the error page dispatching logic back to the ErrorHandler class to assist with backwards compatibility Signed-off-by: Greg Wilkins * Issue #4265 doError Updates from review. Signed-off-by: Greg Wilkins --- .../jetty/alpn/java/server/JDK9ALPNTest.java | 8 +-- .../jetty/client/EmptyServerHandler.java | 4 +- .../eclipse/jetty/client/HttpClientTest.java | 4 +- .../http2/client/http/EmptyServerHandler.java | 4 +- .../HttpServiceErrorPageErrorHandler.java | 2 +- .../org/eclipse/jetty/server/HttpChannel.java | 23 ++------ .../jetty/server/handler/AbstractHandler.java | 17 +++--- .../jetty/server/handler/ErrorHandler.java | 40 ++++++++++---- .../jetty/server/AbstractHttpTest.java | 4 +- .../org/eclipse/jetty/server/DumpHandler.java | 4 +- .../jetty/server/HttpChannelEventTest.java | 4 +- .../jetty/server/HttpConnectionTest.java | 4 +- .../server/HttpManyWaysToAsyncCommitTest.java | 44 ++++++++-------- .../server/HttpManyWaysToCommitTest.java | 52 +++++++++---------- .../jetty/server/HttpServerTestBase.java | 8 +-- .../jetty/server/HttpServerTestFixture.java | 15 +----- .../server/OptionalSslConnectionTest.java | 4 +- .../org/eclipse/jetty/server/RequestTest.java | 4 +- .../server/ServerConnectorTimeoutTest.java | 4 +- .../jetty/server/ServletWriterTest.java | 4 +- .../server/handler/NcsaRequestLogTest.java | 13 ++--- .../ssl/SSLReadEOFAfterResponseTest.java | 4 +- .../ssl/SniSslConnectionFactoryTest.java | 4 +- .../unixsocket/UnixSocketProxyServer.java | 4 +- .../jetty/unixsocket/UnixSocketServer.java | 4 +- .../jetty/unixsocket/UnixSocketTest.java | 4 +- .../jetty/http/client/EmptyServerHandler.java | 4 +- .../http/client/HttpClientContinueTest.java | 4 +- .../http/client/HttpClientStreamTest.java | 4 +- .../jetty/http/client/HttpTrailersTest.java | 20 +++---- .../jetty/http/client/ServerTimeoutsTest.java | 28 +++++----- 31 files changed, 169 insertions(+), 177 deletions(-) diff --git a/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java b/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java index 38582512df9..4163a3facec 100644 --- a/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java +++ b/jetty-alpn/jetty-alpn-java-server/src/test/java/org/eclipse/jetty/alpn/java/server/JDK9ALPNTest.java @@ -80,10 +80,10 @@ public class JDK9ALPNTest @Test public void testClientNotSupportingALPNServerSpeaksDefaultProtocol() throws Exception { - startServer(new AbstractHandler.ErrorDispatchHandler() + startServer(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); } @@ -122,10 +122,10 @@ public class JDK9ALPNTest @Test public void testClientSupportingALPNServerSpeaksNegotiatedProtocol() throws Exception { - startServer(new AbstractHandler.ErrorDispatchHandler() + startServer(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/EmptyServerHandler.java b/jetty-client/src/test/java/org/eclipse/jetty/client/EmptyServerHandler.java index 1287ed445e1..be44bc5d798 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/EmptyServerHandler.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/EmptyServerHandler.java @@ -26,10 +26,10 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; -public class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler +public class EmptyServerHandler extends AbstractHandler { @Override - protected final void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public final void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { jettyRequest.setHandled(true); service(target, jettyRequest, request, response); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java index fe2cbac364c..a938eeb7ab8 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java @@ -535,10 +535,10 @@ public class HttpClientTest extends AbstractHttpClientServerTest @ArgumentsSource(ScenarioProvider.class) public void test_ExchangeIsComplete_OnlyWhenBothRequestAndResponseAreComplete(Scenario scenario) throws Exception { - start(scenario, new AbstractHandler.ErrorDispatchHandler() + start(scenario, new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); response.setContentLength(0); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/EmptyServerHandler.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/EmptyServerHandler.java index 595f77ca933..fc7a42fa533 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/EmptyServerHandler.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/EmptyServerHandler.java @@ -26,10 +26,10 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; -public class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler +public class EmptyServerHandler extends AbstractHandler { @Override - protected final void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public final void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { jettyRequest.setHandled(true); service(target, jettyRequest, request, response); diff --git a/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java b/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java index 85e22fb065c..0f34e781810 100644 --- a/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java +++ b/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java @@ -49,7 +49,7 @@ public class HttpServiceErrorPageErrorHandler extends ErrorPageErrorHandler @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) - throws IOException + throws IOException, ServletException { if (HttpServiceErrorHandlerHelper.getCustomErrorHandler() != null) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index dd1c1a2e571..c8c922746e1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -51,7 +51,6 @@ import org.eclipse.jetty.io.QuietException; import org.eclipse.jetty.server.HttpChannelState.Action; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ErrorHandler; -import org.eclipse.jetty.server.handler.ErrorHandler.ErrorPageMapper; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.SharedBlockingCallback.Blocker; @@ -372,8 +371,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor { if (!_request.hasMetaData()) throw new IllegalStateException("state=" + _state); - _request.setHandled(false); - _response.reopen(); dispatch(DispatcherType.REQUEST, () -> { @@ -391,9 +388,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor case ASYNC_DISPATCH: { - _request.setHandled(false); - _response.reopen(); - dispatch(DispatcherType.ASYNC,() -> getServer().handleAsync(this)); break; } @@ -407,9 +401,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor try { // Get ready to send an error response - _request.setHandled(false); _response.resetContent(); - _response.reopen(); // the following is needed as you cannot trust the response code and reason // as those could have been modified after calling sendError @@ -426,20 +418,11 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor break; } - // Look for an error page dispatcher - String errorPage = (errorHandler instanceof ErrorPageMapper) ? ((ErrorPageMapper)errorHandler).getErrorPage(_request) : null; - Dispatcher errorDispatcher = errorPage != null ? (Dispatcher)context.getRequestDispatcher(errorPage) : null; - if (errorDispatcher == null) + dispatch(DispatcherType.ERROR,() -> { - // Allow ErrorHandler to generate response errorHandler.handle(null, _request, _request, _response); _request.setHandled(true); - } - else - { - // Do the error page dispatch - dispatch(DispatcherType.ERROR,() -> errorDispatcher.error(_request, _response)); - } + }); } catch (Throwable x) { @@ -557,6 +540,8 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor { try { + _request.setHandled(false); + _response.reopen(); _request.setDispatcherType(type); _combinedListener.onBeforeDispatch(_request); dispatchable.dispatch(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java index cb2e2257eb7..fd684c15138 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandler.java @@ -66,11 +66,7 @@ public abstract class AbstractHandler extends ContainerLifeCycle implements Hand public abstract void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; /** - * Convenience method to generate error page. - *

This method can be called from {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} when an {@link DispatcherType#ERROR} dispatch - * is detected and an error page needs to be generated by calling {@link HttpServletResponse#sendError(int, String)} with the appropriate code and reason, - * which are taken from {@link HttpServletRequest#getAttribute(String)} for {@link RequestDispatcher#ERROR_STATUS_CODE} and {@link RequestDispatcher#ERROR_MESSAGE} - * + * Deprecated error page generation * @param target The target of the request - either a URI or a name. * @param baseRequest The original unwrapped request object. * @param request The request either as the {@link Request} object or a wrapper of that request. The @@ -81,16 +77,14 @@ public abstract class AbstractHandler extends ContainerLifeCycle implements Hand * method can be used access the Response object if required. * @throws IOException if unable to handle the request or response processing * @throws ServletException if unable to handle the request or response due to underlying servlet issue - * @see ErrorDispatchHandler for a convenience class that calls this method. */ + @Deprecated protected void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { Object o = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); int code = (o instanceof Integer) ? ((Integer)o).intValue() : (o != null ? Integer.parseInt(o.toString()) : 500); - o = request.getAttribute(RequestDispatcher.ERROR_MESSAGE); - String reason = o != null ? o.toString() : null; - - response.sendError(code, reason); + response.setStatus(code); + baseRequest.setHandled(true); } /* @@ -147,7 +141,9 @@ public abstract class AbstractHandler extends ContainerLifeCycle implements Hand * {@link DispatcherType#ERROR} dispatches are handled by calling the {@link #doError(String, Request, HttpServletRequest, HttpServletResponse)} * method. All other dispatches are passed to the abstract {@link #doNonErrorHandle(String, Request, HttpServletRequest, HttpServletResponse)} * method, which should be implemented with specific handler behavior + * @deprecated This class is no longer required as ERROR dispatch is only done if there is an error page target. */ + @Deprecated public abstract static class ErrorDispatchHandler extends AbstractHandler { @Override @@ -174,6 +170,7 @@ public abstract class AbstractHandler extends ContainerLifeCycle implements Hand * @throws IOException if unable to handle the request or response processing * @throws ServletException if unable to handle the request or response due to underlying servlet issue */ + @Deprecated protected abstract void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index c46b31e342c..39ad8b7f9ac 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -28,6 +28,7 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -82,26 +83,45 @@ public class ErrorHandler extends AbstractHandler } } - /* - * @see org.eclipse.jetty.server.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) - */ - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + // TODO inline this and remove method in jetty-10 doError(target, baseRequest, request, response); } @Override - public void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String cacheControl = getCacheControl(); if (cacheControl != null) response.setHeader(HttpHeader.CACHE_CONTROL.asString(), cacheControl); - String message = (String)request.getAttribute(Dispatcher.ERROR_MESSAGE); - if (message == null) - message = baseRequest.getResponse().getReason(); - generateAcceptableResponse(baseRequest, request, response, response.getStatus(), message); + // Look for an error page dispatcher + // This logic really should be in ErrorPageErrorHandler, but some implementations extend ErrorHandler + // and implement ErrorPageMapper directly, so we do this here in the base class. + String errorPage = (this instanceof ErrorPageMapper) ? ((ErrorPageMapper)this).getErrorPage(request) : null; + ContextHandler.Context context = baseRequest.getErrorContext(); + Dispatcher errorDispatcher = (errorPage != null && context != null) + ? (Dispatcher)context.getRequestDispatcher(errorPage) : null; + + try + { + if (errorDispatcher != null) + { + errorDispatcher.error(request, response); + } + else + { + String message = (String)request.getAttribute(Dispatcher.ERROR_MESSAGE); + if (message == null) + message = baseRequest.getResponse().getReason(); + generateAcceptableResponse(baseRequest, request, response, response.getStatus(), message); + } + } + finally + { + baseRequest.setHandled(true); + } } /** diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java index d554043205c..db77dd4aac9 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/AbstractHttpTest.java @@ -104,7 +104,7 @@ public abstract class AbstractHttpTest } } - protected class ThrowExceptionOnDemandHandler extends AbstractHandler.ErrorDispatchHandler + protected class ThrowExceptionOnDemandHandler extends AbstractHandler { private final boolean throwException; private volatile Throwable failure; @@ -115,7 +115,7 @@ public abstract class AbstractHttpTest } @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (throwException) throw new TestCommitException(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/DumpHandler.java b/jetty-server/src/test/java/org/eclipse/jetty/server/DumpHandler.java index f0d3c859f06..b2e10341126 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/DumpHandler.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/DumpHandler.java @@ -42,7 +42,7 @@ import org.eclipse.jetty.util.log.Logger; * Dumps GET and POST requests. * Useful for testing and debugging. */ -public class DumpHandler extends AbstractHandler.ErrorDispatchHandler +public class DumpHandler extends AbstractHandler { private static final Logger LOG = Log.getLogger(DumpHandler.class); @@ -58,7 +58,7 @@ public class DumpHandler extends AbstractHandler.ErrorDispatchHandler } @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (!isStarted()) return; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpChannelEventTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpChannelEventTest.java index 516a81aeeb2..0e30c7d6850 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpChannelEventTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpChannelEventTest.java @@ -271,10 +271,10 @@ public class HttpChannelEventTest assertTrue(latch.await(5, TimeUnit.SECONDS)); } - private static class TestHandler extends AbstractHandler.ErrorDispatchHandler + private static class TestHandler extends AbstractHandler { @Override - protected final void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public final void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { jettyRequest.setHandled(true); handle(request, response); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java index 715d5ede8a8..278af07753b 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java @@ -1219,11 +1219,11 @@ public class HttpConnectionTest final String longstr = str; final CountDownLatch checkError = new CountDownLatch(1); server.stop(); - server.setHandler(new AbstractHandler.ErrorDispatchHandler() + server.setHandler(new AbstractHandler() { @SuppressWarnings("unused") @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setHeader(HttpHeader.CONTENT_TYPE.toString(), MimeTypes.Type.TEXT_HTML.toString()); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitTest.java index 82d9b06bc3c..3e50d861449 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToAsyncCommitTest.java @@ -126,7 +126,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -140,7 +140,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest asyncContext.complete(); }); } - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -200,7 +200,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -215,7 +215,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -273,7 +273,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -296,7 +296,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -354,7 +354,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -379,7 +379,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -437,7 +437,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -460,7 +460,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -520,7 +520,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -546,7 +546,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -607,7 +607,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -632,7 +632,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -689,7 +689,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -714,7 +714,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -772,7 +772,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -797,7 +797,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -850,7 +850,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -875,7 +875,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -930,7 +930,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, final HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if (request.getAttribute(contextAttribute) == null) { @@ -955,7 +955,7 @@ public class HttpManyWaysToAsyncCommitTest extends AbstractHttpTest }); } baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java index ce6aa58e893..aca8f60d675 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java @@ -84,10 +84,10 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(false); // not needed, but lets be explicit about what the test does - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -125,10 +125,10 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -167,11 +167,11 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.getWriter().write("foobar"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -214,12 +214,12 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.getWriter().write("foobar"); response.flushBuffer(); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -259,11 +259,11 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.flushBuffer(); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -305,13 +305,13 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.getWriter().write("foo"); response.flushBuffer(); response.getWriter().write("bar"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -384,12 +384,12 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setBufferSize(4); response.getWriter().write("foobar"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -401,13 +401,13 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setBufferSize(8); response.getWriter().write("fo"); response.getWriter().write("obarfoobar"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -419,7 +419,7 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setBufferSize(8); @@ -429,7 +429,7 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest response.getWriter().write("fo"); response.getWriter().write("ob"); response.getWriter().write("ar"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -558,12 +558,12 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setContentLength(3); response.getWriter().write("foo"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -603,13 +603,13 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.setContentLength(3); // Only "foo" will get written and "bar" will be discarded response.getWriter().write("foobar"); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -649,12 +649,12 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.getWriter().write("foo"); response.setContentLength(3); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } @@ -694,12 +694,12 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); response.getWriter().write("foobar"); response.setContentLength(3); - super.doNonErrorHandle(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java index fd687f3b7a5..7da99af1b56 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java @@ -283,10 +283,10 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture @Test public void testExceptionThrownInHandler() throws Exception { - configureServer(new AbstractHandler.ErrorDispatchHandler() + configureServer(new AbstractHandler() { @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { throw new QuietServletException("TEST handler exception"); } @@ -314,10 +314,10 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture { final AtomicBoolean fourBytesRead = new AtomicBoolean(false); final AtomicBoolean earlyEOFException = new AtomicBoolean(false); - configureServer(new AbstractHandler.ErrorDispatchHandler() + configureServer(new AbstractHandler() { @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); int contentLength = request.getContentLength(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java index bd009b30d24..ed7e14f01a1 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java @@ -26,7 +26,6 @@ import java.io.PrintWriter; import java.net.Socket; import java.net.URI; import java.nio.charset.StandardCharsets; -import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -212,7 +211,7 @@ public class HttpServerTestFixture } } - protected static class ReadExactHandler extends AbstractHandler.ErrorDispatchHandler + protected static class ReadExactHandler extends AbstractHandler { private int expected; @@ -227,7 +226,7 @@ public class HttpServerTestFixture } @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); int len = expected < 0 ? request.getContentLength() : expected; @@ -247,16 +246,6 @@ public class HttpServerTestFixture response.setContentLength(reply.length()); response.getOutputStream().write(reply.getBytes(StandardCharsets.ISO_8859_1)); } - - @Override - protected void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException - { - System.err.println("ERROR: " + request.getAttribute(RequestDispatcher.ERROR_MESSAGE)); - Throwable th = (Throwable)request.getAttribute(RequestDispatcher.ERROR_EXCEPTION); - if (th != null) - th.printStackTrace(); - super.doError(target, baseRequest, request, response); - } } protected static class ReadHandler extends AbstractHandler diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/OptionalSslConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/OptionalSslConnectionTest.java index 5164a007ceb..a08a177faa2 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/OptionalSslConnectionTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/OptionalSslConnectionTest.java @@ -204,10 +204,10 @@ public class OptionalSslConnectionTest } } - private static class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler + private static class EmptyServerHandler extends AbstractHandler { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { jettyRequest.setHandled(true); } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 522b481fb6a..d5ac2ed0ea8 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -1857,14 +1857,14 @@ public class RequestTest boolean check(HttpServletRequest request, HttpServletResponse response) throws IOException; } - private class RequestHandler extends AbstractHandler.ErrorDispatchHandler + private class RequestHandler extends AbstractHandler { private RequestTester _checker; @SuppressWarnings("unused") private String _content; @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ((Request)request).setHandled(true); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTimeoutTest.java index 6698627fd12..0ddcde76ed7 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTimeoutTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTimeoutTest.java @@ -152,10 +152,10 @@ public class ServerConnectorTimeoutTest extends ConnectorTimeoutTest public void testHttpWriteIdleTimeout() throws Exception { _httpConfiguration.setIdleTimeout(500); - configureServer(new AbstractHandler.ErrorDispatchHandler() + configureServer(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); IO.copy(request.getInputStream(), response.getOutputStream()); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServletWriterTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServletWriterTest.java index 3728880a5f6..8001b189e3c 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ServletWriterTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServletWriterTest.java @@ -72,9 +72,9 @@ public class ServletWriterTest char[] chars = new char[128 * 1024 * 1024]; CountDownLatch latch = new CountDownLatch(1); AtomicReference serverThreadRef = new AtomicReference<>(); - start(chars.length, new AbstractHandler.ErrorDispatchHandler() { + start(chars.length, new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { serverThreadRef.set(Thread.currentThread()); jettyRequest.setHandled(true); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java index e854f3f44f1..dc66ea72fc5 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java @@ -468,10 +468,10 @@ public class NcsaRequestLogTest { setup(logType); _server.setRequestLog(_log); - AbstractHandler.ErrorDispatchHandler wrapper = new AbstractHandler.ErrorDispatchHandler() + AbstractHandler wrapper = new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { testHandler.handle(target, baseRequest, request, response); @@ -484,10 +484,11 @@ public class NcsaRequestLogTest ErrorHandler errorHandler = new ErrorHandler() { @Override - public void doError(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { errors.add(baseRequest.getRequestURI()); - super.doError(target, baseRequest, request, response); + super.handle(target, baseRequest, request, response); } }; _server.addBean(errorHandler); @@ -502,10 +503,10 @@ public class NcsaRequestLogTest { setup(logType); _server.setRequestLog(_log); - AbstractHandler.ErrorDispatchHandler wrapper = new AbstractHandler.ErrorDispatchHandler() + AbstractHandler wrapper = new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { testHandler.handle(target, baseRequest, request, response); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLReadEOFAfterResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLReadEOFAfterResponseTest.java index 7f734a9b688..fa62bfd3a30 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLReadEOFAfterResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLReadEOFAfterResponseTest.java @@ -66,10 +66,10 @@ public class SSLReadEOFAfterResponseTest String content = "the quick brown fox jumped over the lazy dog"; byte[] bytes = content.getBytes(StandardCharsets.UTF_8); - server.setHandler(new AbstractHandler.ErrorDispatchHandler() + server.setHandler(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // First: read the whole content. InputStream input = request.getInputStream(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java index 27c5d89251e..ae8e009bf10 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SniSslConnectionFactoryTest.java @@ -128,10 +128,10 @@ public class SniSslConnectionFactoryTest new HttpConnectionFactory(_httpsConfiguration)); _server.addConnector(https); - _server.setHandler(new AbstractHandler.ErrorDispatchHandler() + _server.setHandler(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) { baseRequest.setHandled(true); response.setStatus(200); diff --git a/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketProxyServer.java b/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketProxyServer.java index 70378fe3d37..93bc0309027 100644 --- a/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketProxyServer.java +++ b/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketProxyServer.java @@ -48,10 +48,10 @@ public class UnixSocketProxyServer if (Files.exists(socket)) Files.delete(socket); - server.setHandler(new AbstractHandler.ErrorDispatchHandler() + server.setHandler(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { int l = 0; if (request.getContentLength() != 0) diff --git a/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketServer.java b/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketServer.java index 62120a76641..bf9b391dc7a 100644 --- a/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketServer.java +++ b/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketServer.java @@ -46,10 +46,10 @@ public class UnixSocketServer if (Files.exists(socket)) Files.delete(socket); - server.setHandler(new AbstractHandler.ErrorDispatchHandler() + server.setHandler(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { int l = 0; if (request.getContentLength() != 0) diff --git a/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketTest.java b/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketTest.java index 6836a5e7fac..88f4c1b76b9 100644 --- a/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketTest.java +++ b/jetty-unixsocket/src/test/java/org/eclipse/jetty/unixsocket/UnixSocketTest.java @@ -102,10 +102,10 @@ public class UnixSocketTest connector.setUnixSocket(sockFile.toString()); server.addConnector(connector); - server.setHandler(new AbstractHandler.ErrorDispatchHandler() + server.setHandler(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { int l = 0; if (request.getContentLength() != 0) diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/EmptyServerHandler.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/EmptyServerHandler.java index 3b8e0da65b1..5440514091e 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/EmptyServerHandler.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/EmptyServerHandler.java @@ -26,10 +26,10 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; -public class EmptyServerHandler extends AbstractHandler.ErrorDispatchHandler +public class EmptyServerHandler extends AbstractHandler { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { jettyRequest.setHandled(true); service(target, jettyRequest, request, response); diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientContinueTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientContinueTest.java index 94c531f0984..9f35cf20889 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientContinueTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientContinueTest.java @@ -742,10 +742,10 @@ public class HttpClientContinueTest extends AbstractTest public void test_NoExpect_Respond100Continue(Transport transport) throws Exception { init(transport); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { jettyRequest.setHandled(true); // Force a 100 Continue response. diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientStreamTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientStreamTest.java index 51ec665f2a1..d413a29972f 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientStreamTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpClientStreamTest.java @@ -497,10 +497,10 @@ public class HttpClientStreamTest extends AbstractTest public void testInputStreamContentProviderThrowingWhileReading(Transport transport) throws Exception { init(transport); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - public void doNonErrorHandle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); IO.copy(request.getInputStream(), response.getOutputStream()); diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java index 602070268d5..ee000ce628a 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java @@ -79,10 +79,10 @@ public class HttpTrailersTest extends AbstractTest { String trailerName = "Trailer"; String trailerValue = "value"; - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { jettyRequest.setHandled(true); @@ -118,10 +118,10 @@ public class HttpTrailersTest extends AbstractTest public void testEmptyRequestTrailers(Transport transport) throws Exception { init(transport); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { jettyRequest.setHandled(true); @@ -167,10 +167,10 @@ public class HttpTrailersTest extends AbstractTest { String trailerName = "Trailer"; String trailerValue = "value"; - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { jettyRequest.setHandled(true); @@ -212,10 +212,10 @@ public class HttpTrailersTest extends AbstractTest public void testEmptyResponseTrailers(Transport transport) throws Exception { init(transport); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { jettyRequest.setHandled(true); @@ -257,10 +257,10 @@ public class HttpTrailersTest extends AbstractTest String trailerName = "Trailer"; String trailerValue = "value"; init(transport); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { jettyRequest.setHandled(true); diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ServerTimeoutsTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ServerTimeoutsTest.java index d90f1a70163..2ef02ae2156 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ServerTimeoutsTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ServerTimeoutsTest.java @@ -426,10 +426,10 @@ public class ServerTimeoutsTest extends AbstractTest long blockingTimeout = 2 * idleTimeout; scenario.httpConfig.setBlockingTimeout(blockingTimeout); CountDownLatch handlerLatch = new CountDownLatch(1); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { try { @@ -487,10 +487,10 @@ public class ServerTimeoutsTest extends AbstractTest { init(transport); CountDownLatch handlerLatch = new CountDownLatch(1); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); AsyncContext asyncContext = request.startAsync(); @@ -551,10 +551,10 @@ public class ServerTimeoutsTest extends AbstractTest init(transport); CountDownLatch handlerLatch = new CountDownLatch(1); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); AsyncContext asyncContext = request.startAsync(); @@ -619,10 +619,10 @@ public class ServerTimeoutsTest extends AbstractTest scenario.requestLog.clear(); scenario.httpConfig.setMinRequestDataRate(bytesPerSecond); CountDownLatch handlerLatch = new CountDownLatch(1); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { try { @@ -683,10 +683,10 @@ public class ServerTimeoutsTest extends AbstractTest int bytesPerSecond = 20; scenario.httpConfig.setMinRequestDataRate(bytesPerSecond); CountDownLatch handlerLatch = new CountDownLatch(1); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); ServletInputStream input = request.getInputStream(); @@ -762,10 +762,10 @@ public class ServerTimeoutsTest extends AbstractTest long idleTimeout = 3 * httpIdleTimeout; scenario.httpConfig.setIdleTimeout(httpIdleTimeout); CountDownLatch handlerLatch = new CountDownLatch(1); - scenario.start(new AbstractHandler.ErrorDispatchHandler() + scenario.start(new AbstractHandler() { @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); AsyncContext asyncContext = request.startAsync(); @@ -946,7 +946,7 @@ public class ServerTimeoutsTest extends AbstractTest assertTrue(clientLatch.await(15, TimeUnit.SECONDS)); } - private static class BlockingReadHandler extends AbstractHandler.ErrorDispatchHandler + private static class BlockingReadHandler extends AbstractHandler { private final CountDownLatch handlerLatch; @@ -956,7 +956,7 @@ public class ServerTimeoutsTest extends AbstractTest } @Override - protected void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); ServletInputStream input = request.getInputStream(); From e09444eeb52c3454c4b78cd27ec47187fc44700e Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Tue, 5 Nov 2019 01:07:34 +0300 Subject: [PATCH 5/5] Issue #3863 - Enforce use of SNI (#4085) * Issue #3863 - Enforce use of SNI. Introduced SslContextFactory.rejectUnmatchedSNIHost (default false) so that if no SNI is sent, or SNI does not match a certificate, then the TLS handshake is aborted. Signed-off-by: Simone Bordet * Issue #3863 - Enforce use of SNI. Updates after review. Introduced SslContextFactory.SNISelector to allow application to write their custom logic to select a certificate based on SNI information. Signed-off-by: Simone Bordet * Issue #3863 Enforce SNI Added two sniRequired fields - one at SslContextLevel and the other at the SecureRequestCustomizer. This allows rejection either at TLS handshake or by 400 response. Signed-off-by: Greg Wilkins * Issue #3863 Enforce SNI cleanups from review Signed-off-by: Greg Wilkins * Issue #3863 Enforce SNI improved comments Signed-off-by: Greg Wilkins * Issue #3863 Enforce SNI syntax sugar Signed-off-by: Greg Wilkins * Issue #3863 SNI Updates from review. Extra test for sniSelector function Signed-off-by: Greg Wilkins --- .../src/main/config/etc/jetty-ssl-context.xml | 1 + .../src/main/config/etc/jetty-ssl.xml | 1 + jetty-server/src/main/config/modules/ssl.mod | 6 + .../jetty/server/SecureRequestCustomizer.java | 55 +++++- .../ssl/SniSslConnectionFactoryTest.java | 184 +++++++++++++----- .../test/resources/jetty-logging.properties | 1 - .../util/ssl/SniX509ExtendedKeyManager.java | 117 ++++++++--- .../jetty/util/ssl/SslContextFactory.java | 130 +++++++++---- 8 files changed, 375 insertions(+), 120 deletions(-) diff --git a/jetty-server/src/main/config/etc/jetty-ssl-context.xml b/jetty-server/src/main/config/etc/jetty-ssl-context.xml index 0a0bbe87906..73f4458a439 100644 --- a/jetty-server/src/main/config/etc/jetty-ssl-context.xml +++ b/jetty-server/src/main/config/etc/jetty-ssl-context.xml @@ -26,6 +26,7 @@ +