Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-doc-format

This commit is contained in:
Chris Walker 2019-07-22 11:39:12 -04:00
commit e3c1925bd7
13 changed files with 431 additions and 45 deletions

12
Jenkinsfile vendored
View File

@ -11,7 +11,7 @@ pipeline {
agent { node { label 'linux' } }
options { timeout(time: 120, unit: 'MINUTES') }
steps {
mavenBuild("jdk11", "-Pmongodb install", "maven3", true) // -Pautobahn
mavenBuild("jdk11", "-Pmongodb install", "maven3", true) // -Pautobahn
// Collect up the jacoco execution results (only on main build)
jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class',
exclusionPattern: '' +
@ -35,19 +35,18 @@ pipeline {
execPattern: '**/target/jacoco.exec',
classPattern: '**/target/classes',
sourcePattern: '**/src/main/java'
junit testResults: '**/target/surefire-reports/*.xml,**/target/autobahntestsuite-reports/*.xml'
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
maven_invoker reportsFilenamePattern: "**/target/invoker-reports/BUILD*.xml", invokerBuildDir: "**/target/it"
junit testResults: '**/target/surefire-reports/*.xml,**/target/invoker-reports/TEST*.xml,**/target/autobahntestsuite-reports/*.xml'
}
}
stage("Build / Test - JDK12") {
agent { node { label 'linux' } }
options { timeout(time: 120, unit: 'MINUTES') }
steps {
mavenBuild("jdk12", "-Pmongodb install", "maven3", true)
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
maven_invoker reportsFilenamePattern: "**/target/invoker-reports/BUILD*.xml", invokerBuildDir: "**/target/it"
junit testResults: '**/target/surefire-reports/*.xml,**/target/invoker-reports/TEST*.xml'
}
}
@ -64,6 +63,7 @@ pipeline {
agent { node { label 'linux' } }
options { timeout(time: 30, unit: 'MINUTES') }
steps {
mavenBuild("jdk11", "install -DskipTests", "maven3", true)
mavenBuild("jdk11", "install checkstyle:check -DskipTests", "maven3", true)
recordIssues(
enabledForFailure: true, aggregatingResults: true,
@ -120,7 +120,7 @@ def slackNotif() {
* @return the Jenkinsfile step representing a maven build
*/
def mavenBuild(jdk, cmdline, mvnName, junitPublishDisabled) {
def localRepo = "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}" // ".repository" //
def localRepo = ".repository" // "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}" //
def settingsName = 'oss-settings.xml'
def mavenOpts = '-Xms1g -Xmx4g -Djava.awt.headless=true'

View File

@ -1,11 +1,205 @@
jetty-10.0.0-SNAPSHOT
jetty-10.0.0-alpha0 - 11 July 2019
+ 113 Add support for NCSA Extended Log File Format
+ 114 Bring back overlay deployer
+ 132 ClientConnector abstraction
+ 207 Support javax.websocket version 1.1
+ 215 Add Conscrypt for native ALPN/TLS/SSL
+ 300 Implement Deflater / Inflater Object Pool
+ 482 [jetty-osgi] The CCL while parsing the xml files should be set to a
combination of Jetty and Bundle-Classloader
+ 592 Support no-value Host header in HttpParser
+ 632 JMX tests rely on fixed port
+ 675 Slf4jLog.ignore() should produce at DEBUG level
+ 676 JavaUtilLog.ignore() should produce at DEBUG level
+ 677 Logging of .ignore() should indicate that it was an "Ignored Exception"
+ 746 Implement Servlet 4.0 Request.getMappings
+ 801 Jetty respond with status 200 instead of 304 while using Servlet 4.0
PushBuilder
+ 809 NPE in WebInfConfiguration for webapp deploy in osgi
+ 987 Can GzipHandler check if .gz file exists only by some paths?
+ 1135 Avoid allocations from Method.getParameterTypes() if possible
+ 1200 Use PathWatcher in DeploymentManager
+ 1350 Dynamic selection of the transport to use based on ALPN on the client
side
+ 1368 Need to support KeyStore/TrustStore with null passwords
+ 1384 Expose StatisticsServlet to webapp
+ 1468 Configure PKIX Revocation Checker for SslContextFactory
+ 1485 Add systemd service file
+ 1498 Add JRTResource to support future Java 9 classloader behaviors
+ 1499 ClasspathPattern needs MODULE ruleset to support future Java 9
classloader behaviors
+ 1503 IPv6 address needs normalization (without brackets) in
ForwardedRequestCustomizer
+ 1551 Move CookieCutter to jetty-http
+ 1571 Support Hazelcast session management in 9.4
+ 1574 TypeUtilTest#testGetLocationOfClass is user settings dependant
+ 1591 JDBCSessionDataStore doesn't work with root context on Oracle DB
+ 1592 CompressedContentFormat.tagEquals() - incorrect comparison of entity
tag hashes
+ 1595 HTTP/2: Avoid sending unnecessary stream WINDOW_UPDATE frames
+ 1599 WebSocketCloseTest fails
+ 1600 Update jndi.mod and plus.mod
+ 1603 WebSocketServerFactory NPE in toString()
+ 1604 WebSocketContainer stop needs improvement
+ 1605 ContainerProvider.getWebSocketContainer() behavior is not to spec
+ 1615 Password defaults in jetty-ssl-context.xml should be removed
+ 1618 AsyncContext.dispatch() does not use raw/encoded URI
+ 1622 HeaderFilter doesn't work if the response has been committed
+ 1623 JettyRunMojo use dependencies from reactor (outputdirectory)
+ 1625 Support new IANA declared Websocket Close Status Codes
+ 1637 Thread per connection retained in HTTP/2
+ 1638 Add it test for Maven Plugin
+ 1642 Using RewriteHandler with AsyncContext.dispatch() and
HttpServletRequestWrapper not possible
+ 1643 ProxyServlet always uses default number of selector threads -
constructor should allow to overwrite the default.
+ 1645 NotSerializableException: DoSFilter when using Non-Clustered Session
Management: File System
+ 1656 Improve configurability of ConnectionPools
+ 1671 Asymmetric usage of trailers in MetaData.Request
+ 1675 Session id should not be logged with INFO level in AbstractSessionCache
+ 1676 Remove Deprecated classes & methods
+ 1679 DeploymentManagerMBean not usable through JMX
+ 1682 Jetty-WarFragmentFolderPath directive has no effect in eclipse runtime
mode except for the first launch
+ 1692 Annotation scanning should ignore `module-info.class` files
+ 1698 Missing WWW-Authenticate from SpnegoAuthenticator when other
Authorization header provided
+ 1746 Remove LICENSE-CONTRIBUTOR?
+ 1836 Migrate Locker implementation to JVM ReentrantLock implementation
+ 1838 Servlet 4.0.0 artifact now available on central.maven.org
+ 1852 Fix quickstart generation for servlet 4.0
+ 1898 Request.getCookie() should ignore invalid cookies
+ 1956 Store and report build information of Jetty
+ 1977 jetty-http-spi tests fail with java9
+ 2061 WebSocket hangs in blockingWrite
+ 2075 Deprecating MultiException
+ 2095 Remove FastCGI multiplexing
+ 2103 Server should open connectors early in start sequence
+ 2108 Update licence headers and plugin for 2018
+ 2172 Support javax.websocket 1.1
+ 2175 Refactor WebSocket close handling
+ 2191 JPMS Support
+ 2431 Upgrade to Junit 5
+ 2868 Adding SPNEGO authentication support for Jetty Client
+ 2901 Introduce HttpConnectionUpgrader as a conversation component in
HttpClient
+ 2909 Remove B64Code
+ 2948 Require JDK 11 for Jetty 10.x
+ 2978 Add module-info.java to relevant Jetty modules
+ 2983 Jetty 10 Configuration abstraction
+ 2985 Jetty 10 Configuration replacement algorithm incorrect
+ 2996 ContextHandler.setDefaultContextPath() not implemented for quickstart.
+ 3009 Update Jetty 10 to use non-LEGACY Compliance Modes
+ 3010 Move old MultiPart parsing implementation to jetty-http
+ 3011 Move HttpCompliance to HttpConfiguration
+ 3012 Refactor HttpCompliance and HttpComplianceSection to be friendlier to
customization
+ 3106 Websocket connection stats and request stats
+ 3129 javax-websocket-common pom.xml is wrong
+ 3139 NPE on
WebSocketServerContainerInitializer.configureContext(ServletContextHandler)
+ 3154 Add support for javax.net.ssl.HostnameVerifier to HttpClient
+ 3159 WebSocket permessage-deflate RSV1 validity check
+ 3162 Use Jetty specific Servlet API jar
+ 3165 Review javax-websocket-server tests
+ 3166 Run of autobahn websocket tests on CI
+ 3167 JavaxWebSocketServerContainerInitializer always creates a HttpClient
+ 3170 WebSocket proxy PoC
+ 3182 Restore websocket example files
+ 3186 Jetty maven plugin - javax.annotation.jar picked up from jetty plugin
rather than from applications classpath
+ 3197 Use jetty specific websocket API jar
+ 3213 MetaInfConfigurationTest tests disabled in jetty-10.0.x
+ 3216 Autobahn WebSocketServer failures in jetty 10
+ 3225 Response.sendError should not set reason.
+ 3246 javax-websocket-tests exception stacktraces
+ 3249 Update to apache jasper 9.0.14 for jetty-10
+ 3274 OSGi versions of java.base classes in
org.apache.felix:org.osgi.foundation:jar conflicts with new rules on Java 9+
+ 3279 WebSocket write may hang forever
+ 3288 Correct websocket artifactIds on jetty-10.0.x
+ 3290 async websocket onOpen, onError and onClose in 10.0.x
+ 3298 Review jetty-10 websocket CompletableFuture usage.
+ 3303 Update to jakarta ee javax artifacts for jetty-10
+ 3308 Remove deprecated methods from sessions
+ 3320 Review Jetty 10 module-info.java
+ 3333 Jetty 10 standalone cannot start on the module-path
+ 3340 Update PushCacheFilter to use Servlet 4.0 APIs
+ 3341 XmlBasedHttpClientProvider in Jetty 10
+ 3351 Restructure jetty-unixsocket module
+ 3374 JSR356 RemoteEndpoint.Async.setSendTimeout() logic invalid in Jetty
10.0.x
+ 3379 Tracking of WebSocket Sessions in WebSocket containers
+ 3380 WebSocket should support jetty-io Connection.Listener
+ 3382 Jetty WebSocket Session.suspend() not implemented
+ 3399 XmlConfiguration jetty.webapps.uri is the uri of the webapp not the
parent dir
+ 3406 restore and fix jetty websocket tests in jetty 10
+ 3412 problems with jetty 10 WebSocket session customizer
+ 3446 allow jetty WebSockets to be upgraded using WebSocketUpgradeFilter in
jetty-10
+ 3453 Removing moved Extension classes from jetty-websocket-api
+ 3458 ensure users of the jetty-websocket-api do not have to see
websocket-core classes
+ 3462 client validation of websocket upgrade response
+ 3465 websocket negotiation of extension configuration parameters
+ 3479 review and cleanup of jetty-websocket-api in jetty-10
+ 3484 ClassCastException when using websocket-core classes in
websocket-servlet
+ 3494 flaky tests in jetty-websocket-tests ClientCloseTest
+ 3564 Update jetty-10.0.x to apache jsp 9.0.19
+ 3608 Reply with 400 Bad request to malformed WebSocket handshake
+ 3616 Backport WebSocket SessionTracker from Jetty 10
+ 3648 javax.websocket client container incorrectly creates Server
SslContextFactory
+ 3661 JettyWebSocketServerContainer exposes websocket common classes
+ 3666 WebSocket - Handling sent 1009 close frame.
+ 3696 Unwrap JavaxWebSocketClientContainer.connectToServer() exceptions
+ 3698 Missing WebSocket ServerContainer after server restart
+ 3700 stackoverflow in WebAppClassLoaderUrlStreamTest
+ 3705 Review ClientUpgradeRequest exception handling
+ 3708 Swap various java.lang.String replace() methods for better performant
ones
+ 3712 change maxIdleTime to idleTimeout in jetty-10 websockets
+ 3719 Clean up jetty-10 modules
+ 3726 Remove OSGi export uses of servlet-api from jetty-util
+ 3731 Add testing of CDI behaviors
+ 3736 NPE from WebAppClassLoader during CDI
+ 3746 ClassCastException in WriteFlusher.java - IdleState cannot be cast to
FailedState
+ 3749 Memory leak while processing AsyncListener annotations
+ 3751 Modern Configure DTD / FPI is used inconsistently
+ 3755 ServerWithAnnotations doesn't do anything
+ 3758 Avoid sending empty trailer frames for http/2 requests
+ 3762 WebSocketConnectionStatsTest test uses port 8080
+ 3782 X-Forwarded-Port overrides X-Forwarded-For
+ 3786 ALPN support for Java 14
+ 3789 XmlConfiguration set from property
+ 3798 ClasspathPattern match method throws NPE. URI can be null
+ 3799 Programmatically added listeners from
ServletContextListener.contextInitialzed() are not called
+ 3804 Weld/CDI XML backwards compat?
+ 3805 XmlConfiguration odd behavior for numbers
+ 3809 sending WebSocket close frame with error StatusCode does not do a hard
close (Jetty-10)
+ 3815 PropertyFileLoginModule adds user principle as a role
+ 3835 WebSocketSession are not being stopped properly
+ 3839 JavaxWebSocketServletContainerInitializer fails
+ 3840 Byte-range request performance problems with large files
+ 3849 ClosedChannelException from jetty-test-webapp javax websocket chat
example
+ 467246 null
+ jetty-10 null
jetty-9.4.19.v20190610 - 10 June 2019
+ 2909 Remove B64Code
+ 3332 jetty-maven-plugin - transitive dependencies not loaded from
"target/classes"
+ 3498 WebSocket Session.suspend() now suspends incoming frames instead
of reads
+ 3498 WebSocket Session.suspend() now suspends incoming frames instead of
reads
+ 3534 Use System nanoTime, not currentTimeMillis for IdleTimeout
+ 3550 Server becomes unresponsive after sitting idle from a load spike
+ 3562 InetAccessHandler should be able to apply to a certain port or

View File

@ -188,7 +188,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
<artifactId>jetty-websocket-client</artifactId>
<version>${project.version}</version>
</dependency>
<!-- http/2 support -->

View File

@ -1,4 +1,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>10.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>build-resources</artifactId>
@ -12,8 +17,10 @@
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<!-- never deploy to a repository, only use in reactor -->
<!-- we would prefer not deploy it but we need as it's not discovered as part of reactor
as it's a dependency of a plugin
<skip>true</skip>
-->
</configuration>
</plugin>
</plugins>

View File

@ -0,0 +1,126 @@
//
// ========================================================================
// 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.client.http;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.Promise;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ResponseTrailerTest extends AbstractTest
{
@Test
public void testEmptyTrailersWithoutContent() throws Exception
{
testEmptyTrailers(null);
}
@Test
public void testEmptyTrailersWithContent() throws Exception
{
testEmptyTrailers("data");
}
public void testEmptyTrailers(String data) throws Exception
{
start(new EmptyServerHandler()
{
@Override
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
{
// Send empty response trailers.
response.setTrailerFields(HashMap::new);
if (data != null)
response.getOutputStream().write(data.getBytes(StandardCharsets.US_ASCII));
}
});
HTTP2Client http2Client = new HTTP2Client();
http2Client.start();
try
{
String host = "localhost";
int port = connector.getLocalPort();
InetSocketAddress address = new InetSocketAddress(host, port);
FuturePromise<Session> sessionPromise = new FuturePromise<>();
http2Client.connect(address, new Session.Listener.Adapter(), sessionPromise);
Session session = sessionPromise.get(5, TimeUnit.SECONDS);
HttpURI uri = new HttpURI("http://" + host + ":" + port + "/");
MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields());
HeadersFrame frame = new HeadersFrame(request, null, true);
BlockingQueue<HeadersFrame> headers = new LinkedBlockingQueue<>();
CountDownLatch latch = new CountDownLatch(1);
session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
{
@Override
public void onHeaders(Stream stream, HeadersFrame frame)
{
headers.offer(frame);
if (frame.isEndStream())
latch.countDown();
}
@Override
public void onData(Stream stream, DataFrame frame, Callback callback)
{
super.onData(stream, frame, callback);
if (frame.isEndStream())
latch.countDown();
}
});
assertTrue(latch.await(5, TimeUnit.SECONDS));
assertEquals(1, headers.size());
frame = headers.poll();
assertNotNull(frame);
assertTrue(frame.getMetaData().isResponse());
}
finally
{
http2Client.stop();
}
}
}

View File

@ -119,9 +119,17 @@ public class HttpTransportOverHTTP2 implements HttpTransport
{
if (lastContent)
{
Supplier<HttpFields> trailers = info.getTrailerSupplier();
if (transportCallback.start(new SendTrailers(getCallback(), trailers), false))
sendDataFrame(content, true, trailers == null, transportCallback);
HttpFields trailers = retrieveTrailers();
if (trailers != null)
{
if (transportCallback.start(new SendTrailers(getCallback(), trailers), false))
sendDataFrame(content, true, false, transportCallback);
}
else
{
if (transportCallback.start(getCallback(), false))
sendDataFrame(content, true, true, transportCallback);
}
}
else
{
@ -137,9 +145,17 @@ public class HttpTransportOverHTTP2 implements HttpTransport
{
if (lastContent)
{
Supplier<HttpFields> trailers = info.getTrailerSupplier();
if (transportCallback.start(new SendTrailers(callback, trailers), true))
sendHeadersFrame(info, trailers == null, transportCallback);
HttpFields trailers = retrieveTrailers();
if (trailers != null)
{
if (transportCallback.start(new SendTrailers(callback, trailers), true))
sendHeadersFrame(info, false, transportCallback);
}
else
{
if (transportCallback.start(callback, true))
sendHeadersFrame(info, true, transportCallback);
}
}
else
{
@ -160,16 +176,24 @@ public class HttpTransportOverHTTP2 implements HttpTransport
{
if (lastContent)
{
Supplier<HttpFields> trailers = metaData.getTrailerSupplier();
SendTrailers sendTrailers = new SendTrailers(callback, trailers);
if (hasContent || trailers == null)
HttpFields trailers = retrieveTrailers();
if (trailers != null)
{
if (transportCallback.start(sendTrailers, false))
sendDataFrame(content, true, trailers == null, transportCallback);
SendTrailers sendTrailers = new SendTrailers(callback, trailers);
if (hasContent)
{
if (transportCallback.start(sendTrailers, false))
sendDataFrame(content, true, false, transportCallback);
}
else
{
sendTrailers.succeeded();
}
}
else
{
sendTrailers.succeeded();
if (transportCallback.start(callback, false))
sendDataFrame(content, true, true, transportCallback);
}
}
else
@ -185,6 +209,17 @@ public class HttpTransportOverHTTP2 implements HttpTransport
}
}
private HttpFields retrieveTrailers()
{
Supplier<HttpFields> supplier = metaData.getTrailerSupplier();
if (supplier == null)
return null;
HttpFields trailers = supplier.get();
if (trailers == null)
return null;
return trailers.size() == 0 ? null : trailers;
}
@Override
public boolean isPushSupported()
{
@ -420,9 +455,9 @@ public class HttpTransportOverHTTP2 implements HttpTransport
private class SendTrailers extends Callback.Nested
{
private final Supplier<HttpFields> trailers;
private final HttpFields trailers;
private SendTrailers(Callback callback, Supplier<HttpFields> trailers)
private SendTrailers(Callback callback, HttpFields trailers)
{
super(callback);
this.trailers = trailers;
@ -431,15 +466,8 @@ public class HttpTransportOverHTTP2 implements HttpTransport
@Override
public void succeeded()
{
if (trailers != null)
{
if (transportCallback.start(getCallback(), false))
sendTrailersFrame(new MetaData(HttpVersion.HTTP_2, trailers.get()), transportCallback);
}
else
{
super.succeeded();
}
if (transportCallback.start(getCallback(), false))
sendTrailersFrame(new MetaData(HttpVersion.HTTP_2, trailers), transportCallback);
}
}
}

View File

@ -6,7 +6,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>infinispan-remote-query</artifactId>
<name>Jetty :: Infinispan Session Manager Remote</name>
<name>Jetty :: Infinispan Session Manager Remote with Querying</name>
<url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.infinispan.remote.query</bundle-symbolic-name>

View File

@ -163,7 +163,7 @@
<dependency>
<groupId>org.apache.aries.spifly</groupId>
<artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
<version>1.2</version>
<version>1.2.3</version>
<scope>test</scope>
<exclusions>
<exclusion>

View File

@ -1907,7 +1907,12 @@ public class Request implements HttpServletRequest
public void setContext(Context context)
{
_newContext = _context != context;
_context = context;
if (context == null)
_context = null;
else
{
_context = context;
}
}
/**

View File

@ -719,6 +719,11 @@ public class Response implements HttpServletResponse
return _outputType == OutputType.WRITER;
}
public boolean isStreaming()
{
return _outputType == OutputType.STREAM;
}
@Override
public PrintWriter getWriter() throws IOException
{

View File

@ -27,7 +27,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -91,10 +90,10 @@ public class ErrorHandler extends AbstractHandler
if (errorPage != null)
{
String oldErrorPage = (String)request.getAttribute(ERROR_PAGE);
ServletContext servletContext = request.getServletContext();
if (servletContext == null)
servletContext = ContextHandler.getCurrentContext();
if (servletContext == null)
ContextHandler.Context context = baseRequest.getContext();
if (context == null)
context = ContextHandler.getCurrentContext();
if (context == null)
{
LOG.warn("No ServletContext for error page {}", errorPage);
}
@ -106,7 +105,7 @@ public class ErrorHandler extends AbstractHandler
{
request.setAttribute(ERROR_PAGE, errorPage);
Dispatcher dispatcher = (Dispatcher)servletContext.getRequestDispatcher(errorPage);
Dispatcher dispatcher = (Dispatcher)context.getRequestDispatcher(errorPage);
try
{
if (LOG.isDebugEnabled())
@ -175,11 +174,10 @@ public class ErrorHandler extends AbstractHandler
for (String mimeType : acceptable)
{
generateAcceptableResponse(baseRequest, request, response, code, message, mimeType);
if (baseRequest.isHandled())
if (response.isCommitted() || baseRequest.getResponse().isWriting() || baseRequest.getResponse().isStreaming())
break;
}
}
baseRequest.setHandled(true);
baseRequest.getResponse().closeOutput();
}

View File

@ -221,6 +221,20 @@ public class ErrorHandlerTest
assertThat(response, containsString("Content-Type: text/html;charset=iso-8859-1"));
}
@Test
public void testMoreSpecificAccept() throws Exception
{
String response = connector.getResponse(
"GET / HTTP/1.1\r\n" +
"Host: Localhost\r\n" +
"Accept: text/html, some/other;specific=true\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 404 "));
assertThat(response, not(containsString("Content-Length: 0")));
assertThat(response, containsString("Content-Type: text/html;charset=iso-8859-1"));
}
@Test
public void test404HtmlAcceptAnyCharset() throws Exception
{

11
pom.xml
View File

@ -153,9 +153,13 @@
<message>[ERROR] OLD JDK [${java.version}] in use. Jetty ${project.version} requires JDK 11 or newer</message>
</requireJavaVersion>
<versionTxtRule implementation="org.eclipse.jetty.toolchain.enforcer.rules.VersionTxtRule" />
<!--
jetty 10 alpha version want to use '-' such 10.0.0-alpha0 so disable all those rules....
<versionOsgiRule implementation="org.eclipse.jetty.toolchain.enforcer.rules.RequireOsgiCompatibleVersionRule" />
<versionRedhatRule implementation="org.eclipse.jetty.toolchain.enforcer.rules.RequireRedhatCompatibleVersionRule" />
<versionDebianRule implementation="org.eclipse.jetty.toolchain.enforcer.rules.RequireDebianCompatibleVersionRule" />
-->
<requireUpperBoundDeps>
<excludes>
<exclude>javax.enterprise:cdi-api</exclude>
@ -439,7 +443,7 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>build-resources</artifactId>
<version>${project.version}</version>
<version>10.0.0-alpha0</version>
</dependency>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
@ -496,6 +500,8 @@
<artifactId>maven-invoker-plugin</artifactId>
<version>3.2.1-SNAPSHOT</version>
<configuration>
<writeJunitReport>true</writeJunitReport>
<junitPackageName>org.eclipse.jetty.maven.its</junitPackageName>
<debug>${it.debug}</debug>
<javaHome>${java.home}</javaHome>
<environmentVariables>
@ -1253,6 +1259,9 @@
</profile>
<profile>
<id>ci</id>
<modules>
<module>aggregates/jetty-all</module>
</modules>
<build>
<pluginManagement>
<plugins>